Skip to content

Commit 8c595e3

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 a630f26 commit 8c595e3

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
@@ -2804,12 +2804,14 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) -
28042804
);
28052805
}
28062806

2807+
let now = time();
2808+
28072809
if rendered_msg.is_gossiped {
2808-
msg.chat_id.set_gossiped_timestamp(context, time()).await?;
2810+
msg.chat_id.set_gossiped_timestamp(context, now).await?;
28092811
}
28102812

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

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

src/contact.rs

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

1733+
let now = SystemTime::now();
1734+
let now_ts = now
1735+
.duration_since(SystemTime::UNIX_EPOCH)
1736+
.unwrap_or_default()
1737+
.as_secs() as i64;
1738+
17331739
// Priority contains all recently seen sorted by the timestamp
17341740
// when they become not recently seen.
17351741
//
@@ -1740,7 +1746,7 @@ impl RecentlySeenLoop {
17401746
.query_map(
17411747
"SELECT id, last_seen FROM contacts
17421748
WHERE last_seen > ?",
1743-
(time() - SEEN_RECENTLY_SECONDS,),
1749+
(now_ts - SEEN_RECENTLY_SECONDS,),
17441750
|row| {
17451751
let contact_id: ContactId = row.get("id")?;
17461752
let last_seen: i64 = row.get("last_seen")?;
@@ -1755,8 +1761,6 @@ impl RecentlySeenLoop {
17551761
.unwrap_or_default();
17561762

17571763
loop {
1758-
let now = SystemTime::now();
1759-
17601764
let (until, contact_id) =
17611765
if let Some((Reverse(timestamp), contact_id)) = unseen_queue.peek() {
17621766
(

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)