This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
possible problem with relative timers
- From: Amos Waterland <apw at us dot ibm dot com>
- To: libc-alpha at sources dot redhat dot com
- Cc: kaz at ashi dot footprints dot net, Tom Gall <tom_gall at vnet dot ibm dot com>
- Date: Tue, 23 Jul 2002 21:51:47 +0000
- Subject: possible problem with relative timers
Hello, I think that there might be a bit of a problem with glibc's
implementation of relative timers. The standard says[1]:
Setting the value of the CLOCK_REALTIME clock via clock_settime()
shall have no effect on threads that are blocked waiting for a
relative time service based upon this clock, including the nanosleep()
function; nor on the expiration of relative timers based upon this
clock. Consequently, these time services shall expire when the
requested relative interval elapses, independently of the new or old
value of the clock.
If I am reading the above right, the below test program[2] should not
wait for ten seconds after the first two signals received. But because
linuxthreads/sysdeps/pthread/timer_routines.c::thread_func() uses this:
if (timer != NULL)
pthread_cond_timedwait (&self->cond, &__timer_mutex,
&timer->expirytime);
to implement wait until timer expiry (lines 443-445), the test program
(when run as root because of the clock_settime() call), does wait for 10
seconds, because pthread_cond_timedwait() takes an absolute time and the
test program temporarily rolls the system time back by 10 seconds.
# ./test0038
received timer signal ...
received timer signal ...
there should not be a 10s wait here ...
received timer signal ...
received timer signal ...
If I have not misunderstood the standard, this is kind of a bad problem,
because I do not know of any way to fix it without changing a lot of the
implementation semantics. Maybe somebody has some ideas? Thanks.
Amos W.
[1] http://www.opengroup.org/onlinepubs/007904975/functions/clock_settime.html
[2]
/* Test for relative timer problem.
* Amos Waterland <apw@us.ibm.com>
* 23 July 2002
*/
#include <errno.h>
#include <error.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
int
main (int argc, char *argv[])
{
int result = 0;
{
const int EVENTS = 2;
int i, r;
timer_t tmr;
sigset_t mask;
struct sigevent sigev;
struct itimerspec its;
struct timespec now, then;
if (sigemptyset (&mask))
error (1, errno, "sigemptyset failed");
if (sigaddset (&mask, SIGRTMIN))
error (1, errno, "sigaddset failed");
if (sigprocmask (SIG_BLOCK, &mask, NULL))
error (1, errno, "sigprocmask failed");
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = SIGRTMIN;
sigev.sigev_value.sival_int = 0;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 500000000; /* .5s */
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 500000000; /* .5s */
if ((r = timer_create (CLOCK_REALTIME, &sigev, &tmr)))
error (1, 1, "timer_create failed");
if ((r = timer_settime (tmr, 0, &its, NULL)))
error (1, 1, "timer_settime failed");
for (i = 0; i < EVENTS; i++)
if ((r = sigwaitinfo (&mask, NULL)) != SIGRTMIN)
error (1, 1, "sigwaitinfo failed");
else
printf ("received timer signal ...\n");
if (clock_gettime (CLOCK_REALTIME, &now))
error (1, errno, "clock_gettime failed");
then.tv_sec = now.tv_sec - 10; /* Set time backwards by 10s. */
then.tv_nsec = now.tv_nsec;
if (clock_settime (CLOCK_REALTIME, &then))
error (1, 1, "clock_settime failed");
printf ("there should not be a 10s wait here ...\n");
for (i = 0; i < EVENTS; i++)
if ((r = sigwaitinfo (&mask, NULL)) != SIGRTMIN)
error (1, 1, "sigwaitinfo failed");
else
printf ("received timer signal ...\n");
if ((r = timer_delete (tmr)))
error (1, 1, "timer_delete failed");
if (clock_gettime (CLOCK_REALTIME, &now))
error (1, errno, "clock_gettime failed");
then.tv_sec = now.tv_sec + 10; /* Restore 10s to clock. */
then.tv_nsec = now.tv_nsec;
if (clock_settime (CLOCK_REALTIME, &then))
error (1, 1, "clock_settime failed");
}
exit (result);
}