Skip to content

Commit a76aca9

Browse files
committed
v.h: Add more robust clock_nanosleep() impl from refmon
On Linux, clock_nanosleep() may return early with EINTR if a signal was received on the sleeping thread. Handle that by sleeping in a loop.
1 parent e10bf8b commit a76aca9

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

include/v.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ typedef struct timeval v_timer;
7272
v_timer v_timer_start(void);
7373
long v_timer_get_ms(v_timer t);
7474
long v_timer_get_us(v_timer t);
75+
/* Note: On Linux, this sleep will resume clock_nanosleep() to finish
76+
up the sleep if we happened to get a signal, such as SIGINT during sleep. */
7577
void v_timer_sleep_ms(int ms);
7678

7779
// --- decl v_arr (Dynamic arrays)
@@ -425,19 +427,28 @@ long v_timer_get_us(v_timer t) {
425427
return ((now.tv_sec - t.tv_sec) * 1000000) + (now.tv_usec - t.tv_usec);
426428
}
427429

428-
#ifdef __linux__
429-
#define _BSD_SOURCE
430-
#include <unistd.h>
430+
#if defined(__linux__)
431+
#define _BSD_SOURCE
432+
#include <unistd.h>
433+
#include <errno.h>
431434
#endif
432435

433436
void v_timer_sleep_ms(int ms) {
434-
#ifdef WINDOWS
437+
#if defined(WINDOWS)
435438
Sleep(ms);
436-
#elif __APPLE__
439+
#elif defined(__APPLE__)
437440
struct timespec ts;
438441
ts.tv_sec = ms / 1000;
439442
ts.tv_nsec = (ms % 1000) * 1000000;
440443
nanosleep(&ts, NULL);
444+
#elif defined (__linux__)
445+
struct timespec ts = { .tv_sec = ms / 1000, .tv_nsec = (ms % 1000) * 1000 * 1000 };
446+
struct timespec rem;
447+
while (clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &rem) == EINTR) {
448+
// We received SIGINT which interrupts this sleep. Continue sleeping.
449+
ts = rem;
450+
rem = (struct timespec){ 0 };
451+
}
441452
#else
442453
struct timeval tv = { 0 };
443454
tv.tv_sec = ms / 1000;

0 commit comments

Comments
 (0)