This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]