about summary refs log tree commit diff
path: root/test-skeleton.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2016-08-26 19:27:16 +0200
committerFlorian Weimer <fweimer@redhat.com>2016-08-26 19:40:17 +0200
commit7e625f7e85b4e88f10dbde35a0641742af581806 (patch)
tree9548c7d75393d1b9cd033ea0c875936bee6f9a52 /test-skeleton.c
parent0ac8ee53e8efbfd6e1c37094b4653f5c2dad65b5 (diff)
downloadglibc-7e625f7e85b4e88f10dbde35a0641742af581806.tar.gz
glibc-7e625f7e85b4e88f10dbde35a0641742af581806.tar.xz
glibc-7e625f7e85b4e88f10dbde35a0641742af581806.zip
nptl: Avoid expected SIGALRM in most tests [BZ #20432]
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.
Diffstat (limited to 'test-skeleton.c')
-rw-r--r--test-skeleton.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/test-skeleton.c b/test-skeleton.c
index 5a90c65826..b24ce1d834 100644
--- a/test-skeleton.c
+++ b/test-skeleton.c
@@ -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 */