From 6f1e52a410612a183222cccbaf4ae963d2de2693 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 13 Dec 2024 14:58:11 +0100 Subject: [PATCH] timer: make timers NONBLOCK to prevent races Signed-off-by: Drew DeVault --- ev/+linux/timers.ha | 14 ++++++++++++-- diff --git a/ev/+linux/timers.ha b/ev/+linux/timers.ha index 2e67a7fd5e4d9144356fe6daa7401f4c112db2ec..6cfa265218680dd564507dd1dc9052200eb8c34b 100644 --- a/ev/+linux/timers.ha +++ b/ev/+linux/timers.ha @@ -13,7 +13,8 @@ loop: *loop, cb: *timercb, clock: time::clock, ) (*file | errors::error) = { - const fd = match (rt::timerfd_create(clock, rt::TFD_CLOEXEC)) { + const fd = match (rt::timerfd_create(clock, + rt::TFD_NONBLOCK | rt::TFD_CLOEXEC)) { case let fd: int => yield fd: io::file; case let errno: rt::errno => @@ -47,7 +48,16 @@ fn timer_ready(timer: *file, ev: *rt::epoll_event) void = { assert(timer.op == op::TIMER); let buf: [8]u8 = [0...]; - io::read(timer.fd, buf)!; + match (io::read(timer.fd, buf)) { + case errors::again => + // This can occur if the timer was reconfigured in an event + // handler while the expiration event was pending in the same + // dispatch of the event loop. Just discard the event in this + // case. + return; + case (io::EOF | io::error) => abort(); + case => void; + }; assert(timer.cb != null); const cb = timer.cb: *timercb; -- 2.48.1