NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/58917: timer_settime and timerfd_settime return absolute time of next event



>Number:         58917
>Category:       kern
>Synopsis:       timer_settime and timerfd_settime return absolute time of next event
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Dec 18 16:20:00 +0000 2024
>Originator:     Taylor R Campbell
>Release:        current, 10, 9, ...
>Organization:
The TimerBSD Remaining
>Environment:
>Description:
timer_settime(2) and timerfd_settime(2) are supposed to return the
relative duration until the event, not the absolute time of the next
event.  But we've implemented them to return the absolute time of the
next event, and we failed to write any automatic tests for this.

POSIX says of timer_settime(2):

> If the argument ovalue is not NULL, the timer_settime() function
> shall store, in the location referenced by ovalue, a value
> representing the previous amount of time before the timer would have
> expired, or zero if the timer was disarmed, together with the
> previous timer reload value.
>
> https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/timer_settime.html

Linux man page says of timerfd_settime(2):

>        If the old_value argument is not NULL, then the itimerspec
>        structure that it points to is used to return the setting of the
>        timer that was current at the time of the call; see the
>        description of timerfd_gettime() following.
>
>    timerfd_gettime()
>        timerfd_gettime() returns, in curr_value, an itimerspec structure
>        that contains the current setting of the timer referred to by the
>        file descriptor fd.
>
>        The it_value field returns the amount of time until the timer
>        will next expire.  If both fields of this structure are zero,
>        then the timer is currently disarmed.  This field always contains
>        a relative value, regardless of whether the TFD_TIMER_ABSTIME
>        flag was specified when setting the timer.
>
> https://www.man7.org/linux/man-pages/man2/timerfd_create.2.html

>How-To-Repeat:
#include <err.h>
#include <stdio.h>
#include <time.h>

int
main(void)
{
	timer_t t;
	struct timespec t0, t1;
	struct itimerspec it, oit;
	int status = 0;

	if (timer_create(CLOCK_MONOTONIC, NULL, &t) == -1)
		err(1, "timer_create");
	if (clock_gettime(CLOCK_MONOTONIC, &t0) == -1)
		err(1, "clock_gettime");
	t1 = t0;
	t1.tv_sec += 1;
	it.it_value = t1;
	it.it_interval = (struct timespec){0,0};
	if (timer_settime(t, TIMER_ABSTIME, &it, NULL) == -1)
		err(1, "timer_settime 1");
	if (timer_settime(t, TIMER_ABSTIME, &it, &oit) == -1)
		err(1, "timer_settime 2");
	printf("timer_settime reports %llds %dns remaining\n",
	    (long long)oit.it_value.tv_sec, (int)oit.it_value.tv_nsec);
	status |= oit.it_value.tv_sec > 0; /* fail if remaining >1sec */
	if (timer_gettime(t, &oit) == -1)
		err(1, "timer_gettime");
	printf("timer_gettime reports %llds %dns remaining\n",
	    (long long)oit.it_value.tv_sec, (int)oit.it_value.tv_nsec);
	status |= oit.it_value.tv_sec > 0; /* fail if remaining >1sec */

	fflush(stdout);
	return ferror(stdout) | status;
}

Example output:

$ ./timer
timer_settime reports 4360366s 902110555ns remaining
timer_gettime reports 1s 95289ns remaining

(Also surprising: that timer_gettime reports a duration remaining greater than 1sec.)
>Fix:
Yes, please!



Home | Main Index | Thread Index | Old Index