public inbox for libc-hacker@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Fix POSIX timers
@ 2004-04-16  2:02 Jakub Jelinek
  2004-04-16 20:00 ` Ulrich Drepper
  2004-04-17  8:56 ` Andreas Jaeger
  0 siblings, 2 replies; 9+ messages in thread
From: Jakub Jelinek @ 2004-04-16  2:02 UTC (permalink / raw)
  To: Ulrich Drepper; +Cc: Glibc hackers

Hi!

SIGEV_THREAD times don't work at all if kernel provides POSIX timers.
The problem is that sigwaitinfo magically removes SIGCANCEL from the
sigset_t passed as first argument, but SIGTIMER == SIGCANCEL.
SIGTIMER is blocked in timer_helper_thread and so could be never delivered.
Fix below.

I have also included a new testcase for timers, but have there 3 FIXMEs
where I'm not sure what exactly POSIX mandates.
http://www.opengroup.org/onlinepubs/007904975/functions/timer_getoverrun.html
has:
The timer_settime() function shall fail if:
     [EINVAL] A value structure specified a nanosecond value less than zero
	      or greater than or equal to 1000 million, and the
	      it_value member of that structure did not specify zero seconds
	      and nanoseconds.
This would suggest to me that it should not fail if
it_value.tv_sec == 0 && it_value.tv_nsec == 0
&& (it_interval.tv_nsec < 0 || it_interval.tv_nsec >= 1000000000)
but both the kernel and sysdeps/pthread/timer_settime.c fails with EINVAL.
If current behaviour is wrong, this can be solved both in userland and/or
the kernel, what is the preference?

For timer_gettime, POSIX says:
The it_interval member of value shall contain the reload value last set by timer_settime().

But kernel doesn't return exactly the it_interval value set by last
timer_settime(), but some value between that and orig it_inverval + timer
resolution.  Again, is this a bug or permissible behaviour.

The testcase below prints a warning about both these things, but doesn't
actually fail if they are encountered, until this is resolved.

Last thing, I wonder if it wouldn't be better to use the same mechanism
for SIGEV_THREAD as for message queues.
Then we could have just one magic helper thread for both mqs and timers.
Kernel could drop current SIGEV_THREAD_ID support in posix_timers.c
(return EINVAL on it) and add SIGEV_THREAD support via netlink.
Unfortunately current posix_timers.c doesn't properly check sigev_notify
values, but this could be worked around in userland (if SIGEV_THREAD
struct sigevent sets sigev_signo to -1, current kernel timer_create
will fail with EINVAL and glibc could fall back to compat stuff).

2004-04-15  Jakub Jelinek  <jakub@redhat.com>

	* rt/Makefile (tests): Add tst-timer4.
	* rt/tst-timer4.c: New test.
nptl/
	* sysdeps/unix/sysv/linux/timer_routines.c: Include errno.h.
	(timer_helper_thread): Use inline rt_sigtimedwait syscall instead
	of calling sigwaitinfo.

--- libc/nptl/sysdeps/unix/sysv/linux/timer_routines.c.jj	2003-04-21 09:38:28.000000000 +0200
+++ libc/nptl/sysdeps/unix/sysv/linux/timer_routines.c	2004-04-15 16:49:55.679087743 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -17,6 +17,7 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <errno.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <stdbool.h>
@@ -61,7 +62,19 @@ timer_helper_thread (void *arg)
     {
       siginfo_t si;
 
-      if (sigwaitinfo (&ss, &si) > 0)
+      /* sigwaitinfo cannot be used here, since it deletes
+	 SIGCANCEL == SIGTIMER from the set.  */
+
+      int oldtype = LIBC_CANCEL_ASYNC ();
+
+      /* XXX The size argument hopefully will have to be changed to the
+	 real size of the user-level sigset_t.  */
+      int result = INLINE_SYSCALL (rt_sigtimedwait, 4, &ss, &si, NULL,
+				   _NSIG / 8);
+
+      LIBC_CANCEL_RESET (oldtype);
+
+      if (result > 0)
 	{
 	  if (si.si_code == SI_TIMER)
 	    {
--- libc/rt/Makefile.jj	2004-04-14 08:59:27.000000000 +0200
+++ libc/rt/Makefile	2004-04-15 14:34:31.000000000 +0200
@@ -44,7 +44,7 @@ librt-routines = $(aio-routines) \
 tests := tst-shm tst-clock tst-clock_nanosleep tst-timer tst-timer2 \
 	 tst-aio tst-aio64 tst-aio2 tst-aio3 tst-aio4 tst-aio5 tst-aio6 \
 	 tst-aio7 tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \
-	 tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-timer3
+	 tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-timer3 tst-timer4
 
 extra-libs := librt
 extra-libs-others := $(extra-libs)
--- libc/rt/tst-timer4.c.jj	2004-04-15 11:26:33.000000000 +0200
+++ libc/rt/tst-timer4.c	2004-04-15 18:34:45.225919063 +0200
@@ -0,0 +1,624 @@
+/* Tests for POSIX timer implementation.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2004
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#if _POSIX_THREADS
+# include <pthread.h>
+
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+timer_t timer_none, timer_sig1, timer_sig2, timer_thr1, timer_thr2;
+
+int thr1_cnt, thr1_err;
+union sigval thr1_sigval;
+struct timespec thr1_ts;
+
+static void
+thr1 (union sigval sigval)
+{
+  pthread_mutex_lock (&lock);
+  thr1_err = clock_gettime (CLOCK_REALTIME, &thr1_ts);
+  if (thr1_cnt >= 5)
+    {
+      struct itimerspec it = { };
+      thr1_err |= timer_settime (timer_thr1, 0, &it, NULL);
+    }
+  thr1_sigval = sigval;
+  ++thr1_cnt;
+  pthread_cond_signal (&cond);
+  pthread_mutex_unlock (&lock);
+}
+
+int thr2_cnt, thr2_err;
+union sigval thr2_sigval;
+size_t thr2_guardsize;
+struct timespec thr2_ts;
+
+static void
+thr2 (union sigval sigval)
+{
+  pthread_attr_t nattr;
+  int err = 0;
+  size_t guardsize = -1;
+  int ret = pthread_getattr_np (pthread_self (), &nattr);
+  if (ret)
+    {
+      errno = ret;
+      printf ("pthread_getattr_np failed: %m\n");
+      err = 1;
+    }
+  else
+    {
+      ret = pthread_attr_getguardsize (&nattr, &guardsize);
+      if (ret)
+        {
+          errno = ret;
+          printf ("pthread_attr_getguardsize failed: %m\n");
+          err = 1;
+        }
+      if (pthread_attr_destroy (&nattr) != 0)
+        {
+          puts ("pthread_attr_destroy failed");
+          err = 1;
+        }
+    }
+  pthread_mutex_lock (&lock);
+  thr2_err = clock_gettime (CLOCK_REALTIME, &thr2_ts) | err;
+  if (thr2_cnt >= 5)
+    {
+      struct itimerspec it = { };
+      thr2_err |= timer_settime (timer_thr2, 0, &it, NULL);
+    }
+  thr2_sigval = sigval;
+  ++thr2_cnt;
+  thr2_guardsize = guardsize;
+  pthread_cond_signal (&cond);
+  pthread_mutex_unlock (&lock);
+}
+
+volatile int sig1_cnt, sig1_err;
+volatile union sigval sig1_sigval;
+struct timespec sig1_ts;
+
+static void
+sig1_handler (int sig, siginfo_t *info, void *ctx)
+{
+  int err = 0;
+  if (sig != SIGRTMIN) err |= 1 << 0;
+  if (info->si_signo != SIGRTMIN) err |= 1 << 1;
+  if (info->si_code != SI_TIMER) err |= 1 << 2;
+  if (clock_gettime (CLOCK_REALTIME, &sig1_ts) != 0)
+    err |= 1 << 3;
+  if (sig1_cnt >= 5)
+    {
+      struct itimerspec it = { };
+      if (timer_settime (timer_sig1, 0, &it, NULL))
+	err |= 1 << 4;
+    }
+  sig1_err |= err;
+  sig1_sigval = info->si_value;
+  ++sig1_cnt;
+}
+
+volatile int sig2_cnt, sig2_err;
+volatile union sigval sig2_sigval;
+struct timespec sig2_ts;
+
+static void
+sig2_handler (int sig, siginfo_t *info, void *ctx)
+{
+  int err = 0;
+  if (sig != SIGRTMIN + 1) err |= 1 << 0;
+  if (info->si_signo != SIGRTMIN + 1) err |= 1 << 1;
+  if (info->si_code != SI_TIMER) err |= 1 << 2;
+  if (clock_gettime (CLOCK_REALTIME, &sig2_ts) != 0)
+    err |= 1 << 3;
+  if (sig2_cnt >= 5)
+    {
+      struct itimerspec it = { };
+      if (timer_settime (timer_sig2, 0, &it, NULL))
+	err |= 1 << 4;
+    }
+  sig2_err |= err;
+  sig2_sigval = info->si_value;
+  ++sig2_cnt;
+}
+
+/* Check if end is later or equal to start + nsec.  */
+static int
+check_ts (const char *name, const struct timespec *start,
+	  const struct timespec *end, long msec)
+{
+  struct timespec ts = *start;
+
+  ts.tv_sec += msec / 1000000;
+  ts.tv_nsec += (msec % 1000000) * 1000;
+  if (ts.tv_nsec >= 1000000000)
+    {
+      ++ts.tv_sec;
+      ts.tv_nsec -= 1000000000;
+    }
+  if (end->tv_sec < ts.tv_sec
+      || (end->tv_sec == ts.tv_sec && end->tv_nsec < ts.tv_nsec))
+    {
+      printf ("timer %s invoked too soon: %ld.%09ld instead of expected %ld.%09ld\n",
+	      name, (long) end->tv_sec, end->tv_nsec,
+	      (long) ts.tv_sec, ts.tv_nsec);
+      return 1;
+    }
+  else
+    return 0;
+}
+
+#define TIMEOUT 15
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  int result = 0;
+
+  struct timespec ts;
+  if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
+    {
+      printf ("clock_gettime failed: %m\n");
+      result = 1;
+    }
+  else
+    printf ("clock_gettime returned timespec = { %ld, %ld }\n",
+	    (long) ts.tv_sec, ts.tv_nsec);
+
+  if (clock_getres (CLOCK_REALTIME, &ts) != 0)
+    {
+      printf ("clock_getres failed: %m\n");
+      result = 1;
+    }
+  else
+    printf ("clock_getres returned timespec = { %ld, %ld }\n",
+	    (long) ts.tv_sec, ts.tv_nsec);
+
+  struct sigevent ev;
+  memset (&ev, 0x11, sizeof (ev));
+  ev.sigev_notify = SIGEV_NONE;
+  if (timer_create (CLOCK_REALTIME, &ev, &timer_none) != 0)
+    {
+      printf ("timer_create for timer_none failed: %m\n");
+      result = 1;
+    }
+
+  struct sigaction sa = { .sa_sigaction = sig1_handler,
+			  .sa_flags = SA_SIGINFO };
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGRTMIN, &sa, NULL);
+  sa.sa_sigaction = sig2_handler;
+  sigaction (SIGRTMIN + 1, &sa, NULL);
+
+  memset (&ev, 0x22, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_ptr = &ev;
+  if (timer_create (CLOCK_REALTIME, &ev, &timer_sig1) != 0)
+    {
+      printf ("timer_create for timer_sig1 failed: %m\n");
+      result = 1;
+    }
+
+  memset (&ev, 0x33, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN + 1;
+  ev.sigev_value.sival_int = 163;
+  if (timer_create (CLOCK_REALTIME, &ev, &timer_sig2) != 0)
+    {
+      printf ("timer_create for timer_sig2 failed: %m\n");
+      result = 1;
+    }
+
+  memset (&ev, 0x44, sizeof (ev));
+  ev.sigev_notify = SIGEV_THREAD;
+  ev.sigev_notify_function = thr1;
+  ev.sigev_notify_attributes = NULL;
+  ev.sigev_value.sival_ptr = &ev;
+  if (timer_create (CLOCK_REALTIME, &ev, &timer_thr1) != 0)
+    {
+      printf ("timer_create for timer_thr1 failed: %m\n");
+      result = 1;
+    }
+
+  pthread_attr_t nattr;
+  if (pthread_attr_init (&nattr)
+      || pthread_attr_setguardsize (&nattr, 0))
+    {
+      puts ("pthread_attr_t setup failed");
+      result = 1;
+    }
+
+  memset (&ev, 0x55, sizeof (ev));
+  ev.sigev_notify = SIGEV_THREAD;
+  ev.sigev_notify_function = thr2;
+  ev.sigev_notify_attributes = &nattr;
+  ev.sigev_value.sival_int = 111;
+  if (timer_create (CLOCK_REALTIME, &ev, &timer_thr2) != 0)
+    {
+      printf ("timer_create for timer_thr2 failed: %m\n");
+      result = 1;
+    }
+
+  int ret = timer_getoverrun (timer_thr1);
+  if (ret != 0)
+    {
+      if (ret == -1)
+	printf ("timer_getoverrun failed: %m\n");
+      else
+	printf ("timer_getoverrun returned %d != 0\n", ret);
+      result = 1;
+    }
+
+  struct itimerspec it;
+  it.it_value.tv_sec = 0;
+  it.it_value.tv_nsec = -26;
+  it.it_interval.tv_sec = 0;
+  it.it_interval.tv_nsec = 0;
+  if (timer_settime (timer_sig1, 0, &it, NULL) == 0)
+    {
+      puts ("timer_settime with negative tv_nsec unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("timer_settime with negative tv_nsec did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 100000;
+  it.it_interval.tv_nsec = 1000000000;
+  if (timer_settime (timer_sig2, 0, &it, NULL) == 0)
+    {
+      puts ("timer_settime with tv_nsec 1000000000 unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("timer_settime with tv_nsec 1000000000 did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 0;
+  it.it_interval.tv_nsec = -26;
+  if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime with it_value 0 it_interval invalid failed: %m\n");
+      /* FIXME: is this mandated by POSIX?
+      result = 1; */
+    }
+
+  it.it_interval.tv_nsec = 3000000000;
+  if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime with it_value 0 it_interval invalid failed: %m\n");
+      /* FIXME: is this mandated by POSIX?
+      result = 1; */
+    }
+
+  struct timespec startts;
+  if (clock_gettime (CLOCK_REALTIME, &startts) != 0)
+    {
+      printf ("clock_gettime failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 100000000;
+  it.it_interval.tv_nsec = 0;
+  if (timer_settime (timer_none, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime timer_none failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 200000000;
+  if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime timer_thr1 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 300000000;
+  if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime timer_thr2 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 400000000;
+  if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime timer_sig1 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 500000000;
+  if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
+    {
+      printf ("timer_settime timer_sig2 failed: %m\n");
+      result = 1;
+    }
+
+  pthread_mutex_lock (&lock);
+  while (thr1_cnt == 0 || thr2_cnt == 0)
+    pthread_cond_wait (&cond, &lock);
+  pthread_mutex_unlock (&lock);
+
+  while (sig1_cnt == 0 || sig2_cnt == 0)
+    {
+      ts.tv_sec = 0;
+      ts.tv_nsec = 100000000;
+      nanosleep (&ts, NULL);
+    }
+
+  pthread_mutex_lock (&lock);
+
+  if (thr1_cnt != 1)
+    {
+      printf ("thr1 not called exactly once, but %d times\n", thr1_cnt);
+      result = 1;
+    }
+  else if (thr1_err)
+    {
+      puts ("an error occurred in thr1");
+      result = 1;
+    }
+  else if (thr1_sigval.sival_ptr != &ev)
+    {
+      printf ("thr1_sigval.sival_ptr %p != %p\n", thr1_sigval.sival_ptr, &ev);
+      result = 1;
+    }
+  else if (check_ts ("thr1", &startts, &thr1_ts, 200000))
+    result = 1;
+
+  if (thr2_cnt != 1)
+    {
+      printf ("thr2 not called exactly once, but %d times\n", thr2_cnt);
+      result = 1;
+    }
+  else if (thr2_err)
+    {
+      puts ("an error occurred in thr2");
+      result = 1;
+    }
+  else if (thr2_sigval.sival_int != 111)
+    {
+      printf ("thr2_sigval.sival_ptr %d != 111\n", thr2_sigval.sival_int);
+      result = 1;
+    }
+  else if (check_ts ("thr2", &startts, &thr2_ts, 300000))
+    result = 1;
+  else if (thr2_guardsize != 0)
+    {
+      printf ("thr2 guardsize %zd != 0\n", thr2_guardsize);
+      result = 1;
+    }
+
+  pthread_mutex_unlock (&lock);
+
+  if (sig1_cnt != 1)
+    {
+      printf ("sig1 not called exactly once, but %d times\n", sig1_cnt);
+      result = 1;
+    }
+  else if (sig1_err)
+    {
+      printf ("errors occurred in sig1 handler %x\n", sig1_err);
+      result = 1;
+    }
+  else if (sig1_sigval.sival_ptr != &ev)
+    {
+      printf ("sig1_sigval.sival_ptr %p != %p\n", sig1_sigval.sival_ptr, &ev);
+      result = 1;
+    }
+  else if (check_ts ("sig1", &startts, &sig1_ts, 400000))
+    result = 1;
+
+  if (sig2_cnt != 1)
+    {
+      printf ("sig2 not called exactly once, but %d times\n", sig2_cnt);
+      result = 1;
+    }
+  else if (sig2_err)
+    {
+      printf ("errors occurred in sig2 handler %x\n", sig2_err);
+      result = 1;
+    }
+  else if (sig2_sigval.sival_int != 163)
+    {
+      printf ("sig2_sigval.sival_ptr %d != 163\n", sig2_sigval.sival_int);
+      result = 1;
+    }
+  else if (check_ts ("sig2", &startts, &sig2_ts, 500000))
+    result = 1;
+
+  if (timer_gettime (timer_none, &it) != 0)
+    {
+      printf ("timer_gettime timer_none failed: %m\n");
+      result = 1;
+    }
+  else if (it.it_value.tv_sec || it.it_value.tv_nsec
+	   || it.it_interval.tv_sec || it.it_interval.tv_nsec)
+    {
+      printf ("timer_gettime timer_none returned { %ld.%09ld, %ld.%09ld }\n",
+	      (long) it.it_value.tv_sec, it.it_value.tv_nsec,
+	      (long) it.it_interval.tv_sec, it.it_interval.tv_nsec);
+      result = 1;
+    }
+
+  if (clock_gettime (CLOCK_REALTIME, &startts) != 0)
+    {
+      printf ("clock_gettime failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_sec = 1;
+  it.it_value.tv_nsec = 0;
+  it.it_interval.tv_sec = 0;
+  it.it_interval.tv_nsec = 100000000;
+  if (timer_settime (timer_none, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime timer_none failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 100000000;
+  it.it_interval.tv_nsec = 200000000;
+  if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime timer_thr1 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 200000000;
+  it.it_interval.tv_nsec = 300000000;
+  if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime timer_thr2 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 300000000;
+  it.it_interval.tv_nsec = 400000000;
+  if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
+    {
+      printf ("timer_settime timer_sig1 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 400000000;
+  it.it_interval.tv_nsec = 500000000;
+  if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
+    {
+      printf ("timer_settime timer_sig2 failed: %m\n");
+      result = 1;
+    }
+
+  pthread_mutex_lock (&lock);
+  while (thr1_cnt < 6 || thr2_cnt < 6)
+    pthread_cond_wait (&cond, &lock);
+  pthread_mutex_unlock (&lock);
+
+  while (sig1_cnt < 6 || sig2_cnt < 6)
+    {
+      ts.tv_sec = 0;
+      ts.tv_nsec = 100000000;
+      nanosleep (&ts, NULL);
+    }
+
+  pthread_mutex_lock (&lock);
+
+  if (thr1_err)
+    {
+      puts ("an error occurred in thr1");
+      result = 1;
+    }
+  else if (check_ts ("thr1", &startts, &thr1_ts, 1100000 + 4 * 200000))
+    result = 1;
+
+  if (thr2_err)
+    {
+      puts ("an error occurred in thr2");
+      result = 1;
+    }
+  else if (check_ts ("thr2", &startts, &thr2_ts, 1200000 + 4 * 300000))
+    result = 1;
+  else if (thr2_guardsize != 0)
+    {
+      printf ("thr2 guardsize %zd != 0\n", thr2_guardsize);
+      result = 1;
+    }
+
+  pthread_mutex_unlock (&lock);
+
+  if (sig1_err)
+    {
+      printf ("errors occurred in sig1 handler %x\n", sig1_err);
+      result = 1;
+    }
+  else if (check_ts ("sig1", &startts, &sig1_ts, 1300000 + 4 * 400000))
+    result = 1;
+
+  if (sig2_err)
+    {
+      printf ("errors occurred in sig2 handler %x\n", sig2_err);
+      result = 1;
+    }
+  else if (check_ts ("sig2", &startts, &sig2_ts, 1400000 + 4 * 500000))
+    result = 1;
+
+  if (timer_gettime (timer_none, &it) != 0)
+    {
+      printf ("timer_gettime timer_none failed: %m\n");
+      result = 1;
+    }
+  else if (it.it_interval.tv_sec || it.it_interval.tv_nsec != 100000000)
+    {
+      printf ("second timer_gettime timer_none returned it_interval %ld.%09ld\n",
+	      (long) it.it_interval.tv_sec, it.it_interval.tv_nsec);
+      /* FIXME: For now disabled.
+      result = 1; */
+    }
+
+  if (timer_delete (timer_none) != 0)
+    {
+      printf ("timer_delete for timer_none failed: %m\n");
+      result = 1;
+    }
+
+  if (timer_delete (timer_sig1) != 0)
+    {
+      printf ("timer_delete for timer_sig1 failed: %m\n");
+      result = 1;
+    }
+
+  if (timer_delete (timer_sig2) != 0)
+    {
+      printf ("timer_delete for timer_sig2 failed: %m\n");
+      result = 1;
+    }
+
+  if (timer_delete (timer_thr1) != 0)
+    {
+      printf ("timer_delete for timer_thr1 failed: %m\n");
+      result = 1;
+    }
+
+  if (timer_delete (timer_thr2) != 0)
+    {
+      printf ("timer_delete for timer_thr2 failed: %m\n");
+      result = 1;
+    }
+  return result;
+}
+#else
+# define TEST_FUNCTION 0
+#endif
+
+#include "../test-skeleton.c"

	Jakub

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Fix POSIX timers
  2004-04-16  2:02 [PATCH] Fix POSIX timers Jakub Jelinek
@ 2004-04-16 20:00 ` Ulrich Drepper
  2004-04-17  8:56 ` Andreas Jaeger
  1 sibling, 0 replies; 9+ messages in thread
From: Ulrich Drepper @ 2004-04-16 20:00 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Glibc hackers

Applied.

-- 
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Fix POSIX timers
  2004-04-16  2:02 [PATCH] Fix POSIX timers Jakub Jelinek
  2004-04-16 20:00 ` Ulrich Drepper
@ 2004-04-17  8:56 ` Andreas Jaeger
  2004-04-17 13:23   ` Andreas Jaeger
                     ` (2 more replies)
  1 sibling, 3 replies; 9+ messages in thread
From: Andreas Jaeger @ 2004-04-17  8:56 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Ulrich Drepper, Glibc hackers

[-- Attachment #1: Type: text/plain, Size: 556 bytes --]


tst-timer4.out fails for me now on Linux/x86-64 running a 2.6.4 kernel
with (using nptl):

clock_gettime returned timespec = { 1082189786, 576892000 }
clock_getres returned timespec = { 0, 999848 }
timer_settime with it_value 0 it_interval invalid failed: Invalid argument
timer_settime with it_value 0 it_interval invalid failed: Invalid argument

Andreas
-- 
 Andreas Jaeger, aj@suse.de, http://www.suse.de/~aj
  SuSE Linux AG, Maxfeldstr. 5, 90409 Nürnberg, Germany
   GPG fingerprint = 93A3 365E CE47 B889 DF7F  FED1 389A 563C C272 A126

[-- Attachment #2: Type: application/pgp-signature, Size: 188 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Fix POSIX timers
  2004-04-17  8:56 ` Andreas Jaeger
@ 2004-04-17 13:23   ` Andreas Jaeger
  2004-04-17 15:47   ` Ulrich Drepper
  2004-04-18  2:02   ` Jakub Jelinek
  2 siblings, 0 replies; 9+ messages in thread
From: Andreas Jaeger @ 2004-04-17 13:23 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Ulrich Drepper, Glibc hackers

[-- Attachment #1: Type: text/plain, Size: 788 bytes --]

Andreas Jaeger <aj@suse.de> writes:

> tst-timer4.out fails for me now on Linux/x86-64 running a 2.6.4 kernel
> with (using nptl):

Fails also with linuxthreads on Linux/x86-64:

$ cat rt/tst-timer4.out
clock_gettime returned timespec = { 1082194388, 779424000 }
clock_getres returned timespec = { 0, 999848 }
timer_settime with it_value 0 it_interval invalid failed: Invalid argument
timer_settime with it_value 0 it_interval invalid failed: Invalid argument
thr2 guardsize 4096 != 0
timer_gettime timer_none returned { -1.598237000, 0.000000000 }
thr2 guardsize 4096 != 0

Andreas
-- 
 Andreas Jaeger, aj@suse.de, http://www.suse.de/~aj
  SuSE Linux AG, Maxfeldstr. 5, 90409 Nürnberg, Germany
   GPG fingerprint = 93A3 365E CE47 B889 DF7F  FED1 389A 563C C272 A126

[-- Attachment #2: Type: application/pgp-signature, Size: 188 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Fix POSIX timers
  2004-04-17  8:56 ` Andreas Jaeger
  2004-04-17 13:23   ` Andreas Jaeger
@ 2004-04-17 15:47   ` Ulrich Drepper
  2004-04-17 15:53     ` Andreas Jaeger
  2004-04-18  2:02   ` Jakub Jelinek
  2 siblings, 1 reply; 9+ messages in thread
From: Ulrich Drepper @ 2004-04-17 15:47 UTC (permalink / raw)
  To: Andreas Jaeger; +Cc: Jakub Jelinek, Glibc hackers

Andreas Jaeger wrote:
> tst-timer4.out fails for me now on Linux/x86-64 running a 2.6.4 kernel
> with (using nptl):
> 
> clock_gettime returned timespec = { 1082189786, 576892000 }
> clock_getres returned timespec = { 0, 999848 }
> timer_settime with it_value 0 it_interval invalid failed: Invalid argument
> timer_settime with it_value 0 it_interval invalid failed: Invalid argument

And what is the exit status of the test program?  It's zero, meaning the
test does not fail.  I've made some changes to disable some tests which
are really undefined and marked the real bugs more clearly.

-- 
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Fix POSIX timers
  2004-04-17 15:47   ` Ulrich Drepper
@ 2004-04-17 15:53     ` Andreas Jaeger
  2004-04-17 15:57       ` Ulrich Drepper
  0 siblings, 1 reply; 9+ messages in thread
From: Andreas Jaeger @ 2004-04-17 15:53 UTC (permalink / raw)
  To: Ulrich Drepper; +Cc: Jakub Jelinek, Glibc hackers

[-- Attachment #1: Type: text/plain, Size: 2902 bytes --]

Ulrich Drepper <drepper@redhat.com> writes:

> Andreas Jaeger wrote:
>> tst-timer4.out fails for me now on Linux/x86-64 running a 2.6.4 kernel
>> with (using nptl):
>> 
>> clock_gettime returned timespec = { 1082189786, 576892000 }
>> clock_getres returned timespec = { 0, 999848 }
>> timer_settime with it_value 0 it_interval invalid failed: Invalid argument
>> timer_settime with it_value 0 it_interval invalid failed: Invalid argument
>
> And what is the exit status of the test program?  It's zero, meaning the

It was non-zero.

> test does not fail.  I've made some changes to disable some tests which
> are really undefined and marked the real bugs more clearly.

Ok, I've just tried your changed version and get:

With nptl:
GCONV_PATH=/builds/glibc/hammer+nptl/iconvdata LC_ALL=C   /builds/glibc/hammer+nptl/elf/ld-linux-x86-64.so.2 --library-path /builds/glibc/hammer+nptl:/builds/glibc/hammer+nptl/math:/builds/glibc/hammer+nptl/elf:/builds/glibc/hammer+nptl/dlfcn:/builds/glibc/hammer+nptl/nss:/builds/glibc/hammer+nptl/nis:/builds/glibc/hammer+nptl/rt:/builds/glibc/hammer+nptl/resolv:/builds/glibc/hammer+nptl/crypt:/builds/glibc/hammer+nptl/nptl /builds/glibc/hammer+nptl/rt/tst-timer4  > /builds/glibc/hammer+nptl/rt/tst-timer4.out
Timed out: killed the child process
make[2]: *** [/builds/glibc/hammer+nptl/rt/tst-timer4.out] Error 1

$ cat rt/tst-timer4.out
clock_gettime returned timespec = { 1082217097, 179058000 }
clock_getres returned timespec = { 0, 999848 }


And with linuxthreads:
GCONV_PATH=/builds/glibc/hammer+linuxthreads/iconvdata LC_ALL=C   /builds/glibc/hammer+linuxthreads/elf/ld-linux-x86-64.so.2 --library-path /builds/glibc/hammer+linuxthreads:/builds/glibc/hammer+linuxthreads/math:/builds/glibc/hammer+linuxthreads/elf:/builds/glibc/hammer+linuxthreads/dlfcn:/builds/glibc/hammer+linuxthreads/nss:/builds/glibc/hammer+linuxthreads/nis:/builds/glibc/hammer+linuxthreads/rt:/builds/glibc/hammer+linuxthreads/resolv:/builds/glibc/hammer+linuxthreads/crypt:/builds/glibc/hammer+linuxthreads/linuxthreads /builds/glibc/hammer+linuxthreads/rt/tst-timer4  > /builds/glibc/hammer+linuxthreads/rt/tst-timer4.out
make[2]: *** [/builds/glibc/hammer+linuxthreads/rt/tst-timer4.out] Error 1
make[2]: Leaving directory `/cvs/libc/rt'
make[1]: *** [rt/tests] Error 2
make[1]: Leaving directory `/cvs/libc'
make: *** [check] Error 2
gromit:/builds/glibc/hammer+linuxthreads:[2]$ cat rt/tst-timer4.out
clock_gettime returned timespec = { 1082217091, 948454000 }
clock_getres returned timespec = { 0, 999848 }
*** thr2 guardsize 4096 != 0
*** timer_gettime timer_none returned { -1.598084000, 0.000000000 }
*** thr2 guardsize 4096 != 0


Andreas
-- 
 Andreas Jaeger, aj@suse.de, http://www.suse.de/~aj
  SuSE Linux AG, Maxfeldstr. 5, 90409 Nürnberg, Germany
   GPG fingerprint = 93A3 365E CE47 B889 DF7F  FED1 389A 563C C272 A126

[-- Attachment #2: Type: application/pgp-signature, Size: 188 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Fix POSIX timers
  2004-04-17 15:53     ` Andreas Jaeger
@ 2004-04-17 15:57       ` Ulrich Drepper
  2004-04-17 16:03         ` Andreas Jaeger
  0 siblings, 1 reply; 9+ messages in thread
From: Ulrich Drepper @ 2004-04-17 15:57 UTC (permalink / raw)
  To: Andreas Jaeger; +Cc: Jakub Jelinek, Glibc hackers

Andreas Jaeger wrote:

> Timed out: killed the child process
> make[2]: *** [/builds/glibc/hammer+nptl/rt/tst-timer4.out] Error 1

Then why did you quote the completely unrelated messages?  The timeout
has completely different, and unknown to me, reasons.  Must be some
problems with your kernel since everything works fine here.

-- 
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Fix POSIX timers
  2004-04-17 15:57       ` Ulrich Drepper
@ 2004-04-17 16:03         ` Andreas Jaeger
  0 siblings, 0 replies; 9+ messages in thread
From: Andreas Jaeger @ 2004-04-17 16:03 UTC (permalink / raw)
  To: Ulrich Drepper; +Cc: Jakub Jelinek, Glibc hackers

[-- Attachment #1: Type: text/plain, Size: 755 bytes --]

Ulrich Drepper <drepper@redhat.com> writes:

> Andreas Jaeger wrote:
>
>> Timed out: killed the child process
>> make[2]: *** [/builds/glibc/hammer+nptl/rt/tst-timer4.out] Error 1
>
> Then why did you quote the completely unrelated messages?  The timeout
> has completely different, and unknown to me, reasons.  Must be some
> problems with your kernel since everything works fine here.

Note that the timeout only occurs with nptl - with linuxthreads I get
also errors.

This is using a 2.6.4 Linux kernel - what are you running on x86-64?

Andreas
-- 
 Andreas Jaeger, aj@suse.de, http://www.suse.de/~aj
  SuSE Linux AG, Maxfeldstr. 5, 90409 Nürnberg, Germany
   GPG fingerprint = 93A3 365E CE47 B889 DF7F  FED1 389A 563C C272 A126

[-- Attachment #2: Type: application/pgp-signature, Size: 188 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] Fix POSIX timers
  2004-04-17  8:56 ` Andreas Jaeger
  2004-04-17 13:23   ` Andreas Jaeger
  2004-04-17 15:47   ` Ulrich Drepper
@ 2004-04-18  2:02   ` Jakub Jelinek
  2 siblings, 0 replies; 9+ messages in thread
From: Jakub Jelinek @ 2004-04-18  2:02 UTC (permalink / raw)
  To: Andreas Jaeger; +Cc: Ulrich Drepper, Glibc hackers

On Sat, Apr 17, 2004 at 10:56:49AM +0200, Andreas Jaeger wrote:
> 
> tst-timer4.out fails for me now on Linux/x86-64 running a 2.6.4 kernel
> with (using nptl):
> 
> clock_gettime returned timespec = { 1082189786, 576892000 }
> clock_getres returned timespec = { 0, 999848 }
> timer_settime with it_value 0 it_interval invalid failed: Invalid argument
> timer_settime with it_value 0 it_interval invalid failed: Invalid argument

These two are guarded with FIXME and don't set result = 1, i.e. don't make
the test fail.
I guess that the test failed for you because of timeout, as Ulrich
apparently has not commited the NPTL part of the patch (the actual fix
for timer_routines.c).

	Jakub

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2004-04-18  2:02 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-04-16  2:02 [PATCH] Fix POSIX timers Jakub Jelinek
2004-04-16 20:00 ` Ulrich Drepper
2004-04-17  8:56 ` Andreas Jaeger
2004-04-17 13:23   ` Andreas Jaeger
2004-04-17 15:47   ` Ulrich Drepper
2004-04-17 15:53     ` Andreas Jaeger
2004-04-17 15:57       ` Ulrich Drepper
2004-04-17 16:03         ` Andreas Jaeger
2004-04-18  2:02   ` Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).