From 322ba68605cedcb9e025f5fa463c0cb55b1844f6 Mon Sep 17 00:00:00 2001 From: Evan Wilde Date: Tue, 3 Jun 2025 09:44:45 -0700 Subject: [PATCH] POSIX: Keep original timeout from sleep call The `dispatch_sema4_timedwait` would reset the `_timeout` to an absolute time after the sleep was interrupted instead of when the sleep was called. Interrupting the process while it was sleeping would result in the new absolute timeout deadline being computed using the `timeout` offset from the time of the interrupt. e.g. if the timeout is 10 seconds, it will be ten seconds from when the process was interrupted because the absolute deadline was recomputed. Interrupting the process repeatedly while sleeping would will make the process go back to sleep instead of waking up when the original absolute deadline was reached. `timeout` is a relative timeout offset. `nsec` and `_timeout` are absolute times since the epoch specifying when the wait should stop. --- src/shims/lock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shims/lock.c b/src/shims/lock.c index 6d0ab8764..85e44544c 100644 --- a/src/shims/lock.c +++ b/src/shims/lock.c @@ -231,10 +231,10 @@ _dispatch_sema4_timedwait(_dispatch_sema4_t *sema, dispatch_time_t timeout) struct timespec _timeout; int ret; + uint64_t nsec = _dispatch_time_nanoseconds_since_epoch(timeout); + _timeout.tv_sec = (__typeof__(_timeout.tv_sec))(nsec / NSEC_PER_SEC); + _timeout.tv_nsec = (__typeof__(_timeout.tv_nsec))(nsec % NSEC_PER_SEC); do { - uint64_t nsec = _dispatch_time_nanoseconds_since_epoch(timeout); - _timeout.tv_sec = (__typeof__(_timeout.tv_sec))(nsec / NSEC_PER_SEC); - _timeout.tv_nsec = (__typeof__(_timeout.tv_nsec))(nsec % NSEC_PER_SEC); ret = sem_timedwait(sema, &_timeout); } while (unlikely(ret == -1 && errno == EINTR));