NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/58919: timer_settime fails to trigger for past times
The following reply was made to PR kern/58919; it has been noted by GNATS.
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: gnats-bugs%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost
Cc:
Subject: Re: kern/58919: timer_settime fails to trigger for past times
Date: Thu, 19 Dec 2024 22:12:16 +0000
For relative timers, the language in POSIX.1-2024 is not very clear
(does the part I quoted apply to the whole paragraph, or only to the
half of the paragraph about absolute timers?), but by analogy with
more explicit language about setitimer in POSIX.1-2008, we might
reasonably conclude that negative relative timers are intended to fail
with EINVAL (not ETIMEDOUT) rather than be treated as having fired
already:
> The setitimer() function shall fail if:
>
> [EINVAL]
> The value argument is not in canonical form. (In canonical form,
> the number of microseconds is a non-negative integer less than
> 1000000 and the number of seconds is a non-negative integer.)
>
https://pubs.opengroup.org/onlinepubs/9699919799/functions/setitimer.html
For absolute timers, the issue is that the timer expiration occurs on
the _next tick_ rather than immediately.
This strikes me as wrong: the timer should have fired already, so it
seems to me the signal should be delivered synchronously with the
timer_settime syscall, just like a pending signal is delivered
synchronously with the sigprocmask(SIG_UNBLOCK) syscall. But we're
not alone in this behaviour (at least Linux defers it a tiny bit too).
The following variant of the how-to-repeat program, which sleeps for
the smallest possible nonzero increment of time (rounded up to one
tick), shows this (and I've incorporated it into t_timer_create.c and
t_timerfd.c):
$ cat timerpastabs1.c
#include <err.h>
#include <signal.h>
#include <time.h>
sig_atomic_t woken;
static void
wakeup(int signo)
{
woken = 1;
}
int
main(void)
{
timer_t t;
struct itimerspec it = {.it_value = {-1, 0}};
struct timespec t0;
if (signal(SIGALRM, wakeup) == SIG_ERR)
err(1, "signal(SIGALRM)");
if (timer_create(CLOCK_MONOTONIC, NULL, &t) == -1)
err(1, "timer_create");
if (clock_gettime(CLOCK_MONOTONIC, &t0) == -1)
err(1, "clock_gettime");
timespecadd(&t0, &it.it_value, &it.it_value);
if (timer_settime(t, TIMER_ABSTIME, &it, NULL) == -1)
err(1, "timer_settime");
if (clock_nanosleep(CLOCK_MONOTONIC, 0,
&(const struct timespec){0,1}, NULL) == -1)
err(1, "clock_nanosleep");
return woken ? 0 : 1;
}
$ make timerpastabs1
cc -O2 -o timerpastabs1 timerpastabs1.c
$ ./timerpastabs1
0
Home |
Main Index |
Thread Index |
Old Index