Skip to content

Commit

Permalink
unix: fix uv_uptime() on linux
Browse files Browse the repository at this point in the history
First check `/proc/uptime`, then fallback to `clock_gettime()`.

Fixes: #3068
Co-authored-by: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-by: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
  • Loading branch information
2 people authored and santigimeno committed Dec 28, 2020
1 parent 4ce3761 commit 77a2394
Showing 1 changed file with 33 additions and 28 deletions.
61 changes: 33 additions & 28 deletions src/unix/linux-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,22 +602,53 @@ int uv_resident_set_memory(size_t* rss) {
return UV_EINVAL;
}

static int uv__slurp(const char* filename, char* buf, size_t len) {
ssize_t n;
int fd;

assert(len > 0);

fd = uv__open_cloexec(filename, O_RDONLY);
if (fd < 0)
return fd;

do
n = read(fd, buf, len - 1);
while (n == -1 && errno == EINTR);

if (uv__close_nocheckstdio(fd))
abort();

if (n < 0)
return UV__ERR(errno);

buf[n] = '\0';

return 0;
}

int uv_uptime(double* uptime) {
static volatile int no_clock_boottime;
char buf[128];
struct timespec now;
int r;

/* Try /proc/uptime first, then fallback to clock_gettime(). */

if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf)))
if (1 == sscanf(buf, "%f", uptime))
return 0;

/* Try CLOCK_BOOTTIME first, fall back to CLOCK_MONOTONIC if not available
* (pre-2.6.39 kernels). CLOCK_MONOTONIC doesn't increase when the system
* is suspended.
*/
if (no_clock_boottime) {
retry: r = clock_gettime(CLOCK_MONOTONIC, &now);
retry_clock_gettime: r = clock_gettime(CLOCK_MONOTONIC, &now);
}
else if ((r = clock_gettime(CLOCK_BOOTTIME, &now)) && errno == EINVAL) {
no_clock_boottime = 1;
goto retry;
goto retry_clock_gettime;
}

if (r)
Expand Down Expand Up @@ -1025,32 +1056,6 @@ void uv__set_process_title(const char* title) {
}


static int uv__slurp(const char* filename, char* buf, size_t len) {
ssize_t n;
int fd;

assert(len > 0);

fd = uv__open_cloexec(filename, O_RDONLY);
if (fd < 0)
return fd;

do
n = read(fd, buf, len - 1);
while (n == -1 && errno == EINTR);

if (uv__close_nocheckstdio(fd))
abort();

if (n < 0)
return UV__ERR(errno);

buf[n] = '\0';

return 0;
}


static uint64_t uv__read_proc_meminfo(const char* what) {
uint64_t rc;
char* p;
Expand Down

0 comments on commit 77a2394

Please sign in to comment.