Skip to content

Commit 819f430

Browse files
committed
Improve heartbeat handling using monotonic clock
1 parent 5765565 commit 819f430

1 file changed

Lines changed: 23 additions & 11 deletions

File tree

src/heartbeat.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,29 @@
2525
#include <string.h>
2626
#include <time.h>
2727

28+
/**
29+
@brief Gets the current monotonic time in seconds.
30+
@return Monotonic time in seconds.
31+
*/
32+
static long get_monotonic_time(void)
33+
{
34+
struct timespec ts;
35+
clock_gettime(CLOCK_MONOTONIC, &ts);
36+
return ts.tv_sec;
37+
}
38+
2839
void heartbeat_update_time(int app_index)
2940
{
3041
Application_t *apps = apps_get_array();
31-
apps[app_index].last_heartbeat = time(NULL);
42+
apps[app_index].last_heartbeat = (time_t)get_monotonic_time();
3243
LOGD("Heartbeat time updated for %s", apps[app_index].name);
3344
}
3445

3546
time_t heartbeat_get_elapsed_time(int app_index)
3647
{
3748
Application_t *apps = apps_get_array();
38-
time_t now = time(NULL);
39-
return now - apps[app_index].last_heartbeat;
49+
long now = get_monotonic_time();
50+
return (time_t)(now - apps[app_index].last_heartbeat);
4051
}
4152

4253
bool heartbeat_is_timeout(int app_index)
@@ -54,19 +65,20 @@ bool heartbeat_is_timeout(int app_index)
5465
return false; // Heartbeat not expected for this app
5566
}
5667

57-
const time_t now = time(NULL);
68+
const long now = get_monotonic_time();
69+
const long elapsed = now - (long)app->last_heartbeat;
5870

59-
if(now < app->last_heartbeat)
71+
// Monotonic clock should never go backwards, but handle edge case
72+
if(elapsed < 0)
6073
{
61-
LOGW("Time anomaly detected for %s (system clock changed?)", app->name);
74+
LOGW("Monotonic time anomaly for %s, resetting", app->name);
6275
heartbeat_update_time(app_index);
63-
return false; // Reset and give another interval
76+
return false;
6477
}
6578

66-
const time_t first_heartbeat_threshold = (time_t)MAX(app->heartbeat_interval, app->heartbeat_delay); // delay is designed to be larger than interval
67-
const time_t regular_threshold = (time_t)app->heartbeat_interval;
68-
const time_t threshold = app->first_heartbeat ? regular_threshold : first_heartbeat_threshold;
69-
const time_t elapsed = now - app->last_heartbeat;
79+
const long first_heartbeat_threshold = (long)MAX(app->heartbeat_interval, app->heartbeat_delay);
80+
const long regular_threshold = (long)app->heartbeat_interval;
81+
const long threshold = app->first_heartbeat ? regular_threshold : first_heartbeat_threshold;
7082

7183
if(elapsed >= threshold)
7284
{

0 commit comments

Comments
 (0)