]> sourceware.org Git - glibc.git/commitdiff
nptl: Avoid expected SIGALRM in most tests [BZ #20432]
authorFlorian Weimer <fweimer@redhat.com>
Fri, 26 Aug 2016 17:27:16 +0000 (19:27 +0200)
committerFlorian Weimer <fweimer@redhat.com>
Fri, 26 Aug 2016 17:40:17 +0000 (19:40 +0200)
Before this change, several tests did not detect early deadlocks
because they used SIGALRM as the expected signal, and they ran
for the full default TIMEOUT seconds.

This commit adds a new delayed_exit function to the test skeleton,
along with several error-checking wrappers to pthread functions.
Additional error checking is introduced into several tests.

15 files changed:
ChangeLog
nptl/tst-cond3.c
nptl/tst-eintr1.c
nptl/tst-eintr2.c
nptl/tst-eintr3.c
nptl/tst-eintr4.c
nptl/tst-eintr5.c
nptl/tst-exit2.c
nptl/tst-exit3.c
nptl/tst-mutex6.c
nptl/tst-rwlock5.c
nptl/tst-sem2.c
nptl/tst-spin3.c
nptl/tst-stdio1.c
test-skeleton.c

index a8aae15e70ac7ba7f19c9ef7b6636d1722a5f18c..f6589b4e14f41786b409db2995ed93ca9e507675 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2016-08-26  Florian Weimer  <fweimer@redhat.com>
+
+       [BZ #20432]
+       Avoid expected SIGALRM signals.
+       * test-skeleton.c (xpthread_sigmask, xpthread_mutex_lock)
+       (xpthread_spin_lock, xpthread_cond_wait, xpthread_barrier_wait)
+       (xpthread_create, xpthread_detach, xpthread_join)
+       (delayed_exit_thread, delayed_exit): New functions.
+       * nptl/tst-cond3 (EXPECTED_SIGNAL): Remove.
+       (tf): Use xpthread_cond_wait.
+       (do_test): Likewise.  Replace alarm with delayed_exit.
+       * nptl/tst-eintr1.c (EXPECTED_SIGNAL, TIMEOUT): Remove.
+       (do_test): Call delayed_exit.  Report failure.
+       * nptl/tst-eintr2.c (EXPECTED_SIGNAL, TIMEOUT): Remove.
+       (do_test): Call delayed_exit.
+       * nptl/tst-eintr3.c (EXPECTED_SIGNAL, TIMEOUT): Remove.
+       (do_test): Call delayed_exit.  Use xpthread_join.  Report error.
+       * nptl/tst-eintr4.c (EXPECTED_SIGNAL, TIMEOUT): Remove.
+       (do_test): Call delayed_exit.  Use xpthread_barrier_wait.  Report
+       error.
+       * nptl/tst-eintr5.c (EXPECTED_SIGNAL, TIMEOUT): Remove.
+       (do_test): Call delayed_exit.  Use xpthread_cond_wait.  Report
+       error.
+       * nptl/tst-exit2.c (EXPECTED_SIGNAL): Remove.
+       (do_test): Call delayed_exit.
+       * nptl/tst-exit3.c (EXPECTED_SIGNAL): Remove.
+       (do_test): Call delayed_exit.
+       * nptl/tst-mutex6.c (EXPECTED_SIGNAL): Remove.
+       (do_test): Call delayed_exit instead of alarm.  Use
+       xpthread_mutex_lock.
+       * nptl/tst-rwlock5.c (EXPECTED_SIGNAL): Remove.
+       (do_test): Call delayed_exit instead of alarm.  Use
+       xpthread_mutex_lock.
+       * nptl/tst-sem2.c (EXPECTED_SIGNAL): Remove.
+       (do_test): Call delayed_exit instead of alarm.
+       * nptl/tst-spin3.c (EXPECTED_SIGNAL): Remove.
+       (do_test): Call delayed_exit instead of alarm.  Use
+       xpthread_spin_lock.
+       * nptl/tst-stdio1.c (EXPECTED_SIGNAL): Remove.
+       (do_test): Call delayed_exit instead of alarm.  Use
+       xpthread_join.
+
 2016-08-26  H.J. Lu  <hongjiu.lu@intel.com>
 
        * sysdeps/x86_64/dl-trampoline.h (_dl_runtime_resolve): Don't
index ff904e4378ea39abc09dcf0a936b8003aca00b74..546564fad0c0af181bd6a208c5c4b924fb0da190 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
 
 /* Note that this test requires more than the standard.  It is
    required that there are no spurious wakeups if only more readers
@@ -50,7 +54,8 @@ tf (void *arg)
     }
 
   /* This call should never return.  */
-  pthread_cond_wait (&cond, &mut);
+  xpthread_cond_wait (&cond, &mut);
+  puts ("error: pthread_cond_wait in tf returned");
 
   /* We should never get here.  */
   exit (1);
@@ -96,17 +101,11 @@ do_test (void)
        }
     }
 
-  /* Set an alarm for 1 second.  The wrapper will expect this.  */
-  alarm (1);
+  delayed_exit (1);
 
   /* This call should never return.  */
-  pthread_cond_wait (&cond, &mut);
+  xpthread_cond_wait (&cond, &mut);
 
-  puts ("cond_wait returned");
+  puts ("error: pthread_cond_wait in do_test returned");
   return 1;
 }
-
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index 11cd876a74c5a4e86cb5ef435e68359cdf0748d0..0946894fbed1c66a625365eccb662452d8c30fb2 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
 #include "eintr.c"
 
 
@@ -92,13 +97,8 @@ do_test (void)
        }
     }
 
+  delayed_exit (3);
+  /* This call must never return.  */
   (void) tf1 (NULL);
-  /* NOTREACHED */
-
-  return 0;
+  return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TIMEOUT 3
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index 7f50f4bcf401362f5a561c574bae1ec4f8bf8d9a..0ef6d304743132bda28a480fabfa5f7ab9714c62 100644 (file)
 #include <string.h>
 #include <sys/time.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
 #include "eintr.c"
 
 
@@ -103,6 +108,7 @@ do_test (void)
       exit (1);
     }
 
+  delayed_exit (3);
   /* This call must never return.  */
   e = pthread_mutex_lock (&m1);
   printf ("main: mutex_lock returned: %s\n",
@@ -110,8 +116,3 @@ do_test (void)
 
   return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TIMEOUT 3
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index d2c32b970ad355f9ece27b02203121f05bd323a3..f6b2ccf6810e43950e06276c5ca81c5ab1bf259c 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
 #include "eintr.c"
 
 
@@ -56,16 +61,9 @@ do_test (void)
       exit (1);
     }
 
+  delayed_exit (1);
   /* This call must never return.  */
-  e = pthread_join (th, NULL);
-
-  if (e == EINTR)
-    puts ("pthread_join returned with EINTR");
-
-  return 0;
+  xpthread_join (th);
+  puts ("error: pthread_join returned");
+  return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TIMEOUT 1
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index 25fae34560409fde59533e1d612a811c5c890a1c..f6d068f334cbd2b67f1021eb9d730f0468e75ea0 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
 #include "eintr.c"
 
 
@@ -40,16 +45,9 @@ do_test (void)
       exit (1);
     }
 
+  delayed_exit (1);
   /* This call must never return.  */
-  int e = pthread_barrier_wait (&b);
-
-  if (e == EINTR)
-    puts ("pthread_join returned with EINTR");
-
-  return 0;
+  xpthread_barrier_wait (&b);
+  puts ("error: pthread_barrier_wait returned");
+  return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TIMEOUT 1
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index be6731c798da2389e77f758afa5767fad0392061..81f900e8b9518445611c55f3be71fa55e719b7dc 100644 (file)
 #include <string.h>
 #include <sys/time.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
 #include "eintr.c"
 
 
@@ -66,15 +71,9 @@ do_test (void)
       exit (1);
     }
 
+  delayed_exit (3);
   /* This call must never return.  */
-  e = pthread_cond_wait (&c, &m);
-  printf ("main: cond_wait returned: %s\n",
-         strerror_r (e, buf, sizeof (buf)));
-
-  return 0;
+  xpthread_cond_wait (&c, &m);
+  puts ("error: pthread_cond_wait returned");
+  return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TIMEOUT 3
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index 3f5ff27b0fdd545aff0dcb34b117fe1d87b38e73..0b7a2caf6ae3eacb379eced1ce7c59d8dcae07a7 100644 (file)
@@ -4,6 +4,10 @@
 #include <string.h>
 #include <unistd.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
 
 static void *
 tf (void *arg)
@@ -28,13 +32,11 @@ do_test (void)
       return 1;
     }
 
+  delayed_exit (1);
+
   /* Terminate only this thread.  */
   pthread_exit (NULL);
 
   /* NOTREACHED */
   return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index da92c82c0e9e21c8429582362ba12114e8386c41..9481ed9b420e22c2d37060cb7097c2499f2c5772 100644 (file)
@@ -5,6 +5,10 @@
 #include <string.h>
 #include <unistd.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
 
 static pthread_barrier_t b;
 
@@ -69,13 +73,11 @@ do_test (void)
       exit (1);
     }
 
+  delayed_exit (3);
+
   /* Terminate only this thread.  */
   pthread_exit (NULL);
 
   /* NOTREACHED */
   return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index 1940687feef21eebbded4725404953579330e2b2..3e989d8f55bbf05a7ef10667bca39e2d9f57c575 100644 (file)
 #include <errno.h>
 #include <stdbool.h>
 
+#ifndef TEST_FUNCTION
+static int do_test (void);
+# define TEST_FUNCTION do_test ()
+#endif
+#include "../test-skeleton.c"
 
 #ifndef ATTR
 pthread_mutexattr_t *attr;
@@ -62,18 +67,10 @@ do_test (void)
       return 1;
     }
 
-  /* Set an alarm for 1 second.  The wrapper will expect this.  */
-  alarm (1);
-
+  delayed_exit (1);
   /* This call should never return.  */
-  pthread_mutex_lock (&m);
+  xpthread_mutex_lock (&m);
 
   puts ("2nd mutex_lock returned");
   return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#ifndef TEST_FUNCTION
-# define TEST_FUNCTION do_test ()
-#endif
-#include "../test-skeleton.c"
index b6c5d8a247594648c1868bea24bc316423396815..20fb47182375d0ee80b4a37800a2f721b4c6c9d9 100644 (file)
 #include <stdlib.h>
 #include <unistd.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
 
 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
 static pthread_rwlock_t r;
@@ -65,22 +69,16 @@ do_test (void)
       return 1;
     }
 
-  /* Set an alarm for 1 second.  The wrapper will expect this.  */
-  alarm (1);
-
   if (pthread_create (&th, NULL, tf, NULL) != 0)
     {
       puts ("create failed");
       return 1;
     }
 
+  delayed_exit (1);
   /* This call should never return.  */
-  pthread_mutex_lock (&m);
+  xpthread_mutex_lock (&m);
 
   puts ("2nd mutex_lock returned");
   return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index 301dde7948b4aab3797fbd35d3ef2329831dc974..1f609fcf88b5e71b7410766cb89e04976d9a2469 100644 (file)
    <http://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
+#include <pthread.h>
 #include <semaphore.h>
 #include <signal.h>
 #include <stdio.h>
 #include <unistd.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
 
 static int
 do_test (void)
@@ -34,8 +39,7 @@ do_test (void)
       return 1;
     }
 
-  /* Set an alarm for 1 second.  The wrapper will expect this.  */
-  alarm (1);
+  delayed_exit (1);
 
   if (TEMP_FAILURE_RETRY (sem_wait (&s)) == -1)
     {
@@ -47,7 +51,3 @@ do_test (void)
   puts ("wait succeeded");
   return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index 8964ecca8b05e587f25e82ae66211af4781e5838..6cb6f9d48c38f76f353c5e5de34ffc60f22756be 100644 (file)
 #include <stdio.h>
 #include <unistd.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
 
 static int
 do_test (void)
@@ -39,16 +43,11 @@ do_test (void)
       return 1;
     }
 
-  /* Set an alarm for 1 second.  The wrapper will expect this.  */
-  alarm (1);
+  delayed_exit (1);
 
   /* This call should never return.  */
-  pthread_spin_lock (&s);
+  xpthread_spin_lock (&s);
 
   puts ("2nd spin_lock returned");
   return 1;
 }
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index 2d44c16a77596c0d0c5948d819f13be1af8eda20..4250e53750195b66566a4e2ed195997a683160f5 100644 (file)
 #include <stdio.h>
 #include <unistd.h>
 
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
 
 static void *tf (void *a)
 {
@@ -43,14 +47,10 @@ do_test (void)
       _exit (1);
     }
 
-  pthread_join (th, NULL);
+  delayed_exit (1);
+  xpthread_join (th);
 
   puts ("join returned");
 
-  return 0;
+  return 1;
 }
-
-
-#define EXPECTED_SIGNAL SIGALRM
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
index 5a90c65826011ceff652071f252a9750e5a2fbf8..b24ce1d8342917d3e4ea8382e877bfcc5dc3c873 100644 (file)
@@ -559,3 +559,160 @@ main (int argc, char *argv[])
 #endif
     }
 }
+
+/* The following functionality is only available if <pthread.h> was
+   included before this file.  */
+#ifdef _PTHREAD_H
+
+/* Call pthread_sigmask with error checking.  */
+static void
+xpthread_sigmask (int how, const sigset_t *set, sigset_t *oldset)
+{
+  if (pthread_sigmask (how, set, oldset) != 0)
+    {
+      write_message ("error: pthread_setmask failed\n");
+      _exit (1);
+    }
+}
+
+/* Call pthread_mutex_lock with error checking.  */
+__attribute__ ((unused))
+static void
+xpthread_mutex_lock (pthread_mutex_t *mutex)
+{
+  int ret = pthread_mutex_lock (mutex);
+  if (ret != 0)
+    {
+      errno = ret;
+      printf ("error: pthread_mutex_lock: %m\n");
+      exit (1);
+    }
+}
+
+/* Call pthread_spin_lock with error checking.  */
+__attribute__ ((unused))
+static void
+xpthread_spin_lock (pthread_spinlock_t *lock)
+{
+  int ret = pthread_spin_lock (lock);
+  if (ret != 0)
+    {
+      errno = ret;
+      printf ("error: pthread_spin_lock: %m\n");
+      exit (1);
+    }
+}
+
+/* Call pthread_cond_wait with error checking.  */
+__attribute__ ((unused))
+static void
+xpthread_cond_wait (pthread_cond_t * cond,
+                   pthread_mutex_t * mutex)
+{
+  int ret = pthread_cond_wait (cond, mutex);
+  if (ret != 0)
+    {
+      errno = ret;
+      printf ("error: pthread_cond_wait: %m\n");
+      exit (1);
+    }
+}
+
+/* Call pthread_barrier_wait with error checking.  */
+__attribute__ ((unused))
+static int
+xpthread_barrier_wait (pthread_barrier_t *barrier)
+{
+  int ret = pthread_barrier_wait (barrier);
+  if (ret != 0 && ret != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      errno = ret;
+      printf ("error: pthread_barrier_wait: %m\n");
+      exit (1);
+    }
+  return ret;
+}
+
+/* Call pthread_create with error checking.  */
+static pthread_t
+xpthread_create (pthread_attr_t *attr,
+                void *(*thread_func) (void *), void *closure)
+{
+  pthread_t thr;
+  int ret = pthread_create (&thr, attr, thread_func, closure);
+  if (ret != 0)
+    {
+      errno = ret;
+      printf ("error: pthread_create: %m\n");
+      exit (1);
+    }
+  return thr;
+}
+
+/* Call pthread_detach with error checking.  */
+static void
+xpthread_detach (pthread_t thr)
+{
+  int ret = pthread_detach (thr);
+  if (ret != 0)
+    {
+      errno = ret;
+      printf ("error: pthread_detach: %m\n");
+      exit (1);
+    }
+}
+
+/* Call pthread_join with error checking.  */
+__attribute__ ((unused))
+static void *
+xpthread_join (pthread_t thr)
+{
+  void *result;
+  int ret = pthread_join (thr, &result);
+  if (ret != 0)
+    {
+      errno = ret;
+      printf ("error: pthread_join: %m\n");
+      exit (1);
+    }
+  return result;
+}
+
+/* Used to implement the delayed_exit function defined below.  */
+static void *
+delayed_exit_thread (void *seconds_as_ptr)
+{
+  int seconds = (uintptr_t) seconds_as_ptr;
+  struct timespec delay = { seconds, 0 };
+  struct timespec remaining = {};
+  if (nanosleep (&delay, &remaining) != 0)
+    {
+      printf ("error: nanosleep: %m\n");
+      _exit (1);
+    }
+  /* Exit the process sucessfully.  */
+  exit (0);
+  return NULL;
+}
+
+/* Exit (with status 0) after SECONDS have elapsed, from a helper
+   thread.  The process is terminated with the exit function, so
+   atexit handlers are executed.  */
+__attribute__ ((unused))
+static void
+delayed_exit (int seconds)
+{
+  /* Create the new thread with all signals blocked.  */
+  sigset_t all_blocked;
+  sigfillset (&all_blocked);
+  sigset_t old_set;
+  xpthread_sigmask (SIG_SETMASK, &all_blocked, &old_set);
+  /* Create a detached thread. */
+  pthread_t thr = xpthread_create
+    (NULL, delayed_exit_thread, (void *) (uintptr_t) seconds);
+  xpthread_detach (thr);
+  /* Restore the original signal mask.  */
+  xpthread_sigmask (SIG_SETMASK, &old_set, NULL);
+}
+
+#endif /* _PTHREAD_H */
This page took 0.179253 seconds and 5 git commands to generate.