Skip to content

Commit fe3c1f6

Browse files
committed
feat: Cache system time instead of looking at the clock several times in a row
The system clock may be adjusted and even go back, so caching system time in code sections where it's not supposed to change may even protect from races/bugs.
1 parent 31ee3fe commit fe3c1f6

File tree

5 files changed

+32
-15
lines changed

5 files changed

+32
-15
lines changed

src/chat.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2806,12 +2806,14 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) -
28062806
);
28072807
}
28082808

2809+
let now = time();
2810+
28092811
if rendered_msg.is_gossiped {
2810-
msg.chat_id.set_gossiped_timestamp(context, time()).await?;
2812+
msg.chat_id.set_gossiped_timestamp(context, now).await?;
28112813
}
28122814

28132815
if let Some(last_added_location_id) = rendered_msg.last_added_location_id {
2814-
if let Err(err) = location::set_kml_sent_timestamp(context, msg.chat_id, time()).await {
2816+
if let Err(err) = location::set_kml_sent_timestamp(context, msg.chat_id, now).await {
28152817
error!(context, "Failed to set kml sent_timestamp: {err:#}.");
28162818
}
28172819
if !msg.hidden {
@@ -2830,7 +2832,7 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) -
28302832
}
28312833

28322834
if attach_selfavatar {
2833-
if let Err(err) = msg.chat_id.set_selfavatar_timestamp(context, time()).await {
2835+
if let Err(err) = msg.chat_id.set_selfavatar_timestamp(context, now).await {
28342836
error!(context, "Failed to set selfavatar timestamp: {err:#}.");
28352837
}
28362838
}

src/contact.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,12 @@ impl RecentlySeenLoop {
17321732
async fn run(context: Context, interrupt: Receiver<RecentlySeenInterrupt>) {
17331733
type MyHeapElem = (Reverse<i64>, ContactId);
17341734

1735+
let now = SystemTime::now();
1736+
let now_ts = now
1737+
.duration_since(SystemTime::UNIX_EPOCH)
1738+
.unwrap_or_default()
1739+
.as_secs() as i64;
1740+
17351741
// Priority contains all recently seen sorted by the timestamp
17361742
// when they become not recently seen.
17371743
//
@@ -1742,7 +1748,7 @@ impl RecentlySeenLoop {
17421748
.query_map(
17431749
"SELECT id, last_seen FROM contacts
17441750
WHERE last_seen > ?",
1745-
(time() - SEEN_RECENTLY_SECONDS,),
1751+
(now_ts - SEEN_RECENTLY_SECONDS,),
17461752
|row| {
17471753
let contact_id: ContactId = row.get("id")?;
17481754
let last_seen: i64 = row.get("last_seen")?;
@@ -1757,8 +1763,6 @@ impl RecentlySeenLoop {
17571763
.unwrap_or_default();
17581764

17591765
loop {
1760-
let now = SystemTime::now();
1761-
17621766
let (until, contact_id) =
17631767
if let Some((Reverse(timestamp), contact_id)) = unseen_queue.peek() {
17641768
(

src/imex.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ async fn export_backup(context: &Context, dir: &Path, passphrase: String) -> Res
534534
let _d1 = DeleteOnDrop(temp_db_path.clone());
535535
let _d2 = DeleteOnDrop(temp_path.clone());
536536

537-
export_database(context, &temp_db_path, passphrase)
537+
export_database(context, &temp_db_path, passphrase, now)
538538
.await
539539
.context("could not export database")?;
540540

@@ -770,19 +770,27 @@ where
770770
/// overwritten.
771771
///
772772
/// This also verifies that IO is not running during the export.
773-
async fn export_database(context: &Context, dest: &Path, passphrase: String) -> Result<()> {
773+
async fn export_database(
774+
context: &Context,
775+
dest: &Path,
776+
passphrase: String,
777+
timestamp: i64,
778+
) -> Result<()> {
774779
ensure!(
775780
!context.scheduler.is_running().await,
776781
"cannot export backup, IO is running"
777782
);
778-
let now = time().try_into().context("32-bit UNIX time overflow")?;
783+
let timestamp = timestamp.try_into().context("32-bit UNIX time overflow")?;
779784

780785
// TODO: Maybe introduce camino crate for UTF-8 paths where we need them.
781786
let dest = dest
782787
.to_str()
783788
.with_context(|| format!("path {} is not valid unicode", dest.display()))?;
784789

785-
context.sql.set_raw_config_int("backup_time", now).await?;
790+
context
791+
.sql
792+
.set_raw_config_int("backup_time", timestamp)
793+
.await?;
786794
sql::housekeeping(context).await.log_err(context).ok();
787795
context
788796
.sql

src/imex/transfer.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use crate::context::Context;
5252
use crate::message::{Message, Viewtype};
5353
use crate::qr::{self, Qr};
5454
use crate::stock_str::backup_transfer_msg_body;
55+
use crate::tools::time;
5556
use crate::{e2ee, EventType};
5657

5758
use super::{export_database, DBFILE_BACKUP_NAME};
@@ -158,7 +159,7 @@ impl BackupProvider {
158159
// Generate the token up front: we also use it to encrypt the database.
159160
let token = AuthToken::generate();
160161
context.emit_event(SendProgress::Started.into());
161-
export_database(context, dbfile, token.to_string())
162+
export_database(context, dbfile, token.to_string(), time())
162163
.await
163164
.context("Database export failed")?;
164165
context.emit_event(SendProgress::DatabaseExported.into());

src/location.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,9 @@ impl Kml {
139139
match chrono::NaiveDateTime::parse_from_str(&val, "%Y-%m-%dT%H:%M:%SZ") {
140140
Ok(res) => {
141141
self.curr.timestamp = res.timestamp();
142-
if self.curr.timestamp > time() {
143-
self.curr.timestamp = time();
142+
let now = time();
143+
if self.curr.timestamp > now {
144+
self.curr.timestamp = now;
144145
}
145146
}
146147
Err(_err) => {
@@ -333,12 +334,13 @@ pub async fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64
333334
return Ok(true);
334335
}
335336
let mut continue_streaming = false;
337+
let now = time();
336338

337339
let chats = context
338340
.sql
339341
.query_map(
340342
"SELECT id FROM chats WHERE locations_send_until>?;",
341-
(time(),),
343+
(now,),
342344
|row| row.get::<_, i32>(0),
343345
|chats| {
344346
chats
@@ -356,7 +358,7 @@ pub async fn set(context: &Context, latitude: f64, longitude: f64, accuracy: f64
356358
latitude,
357359
longitude,
358360
accuracy,
359-
time(),
361+
now,
360362
chat_id,
361363
ContactId::SELF,
362364
)).await.context("Failed to store location")?;

0 commit comments

Comments
 (0)