aboutsummaryrefslogtreecommitdiff
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
parent0ac8ee53e8efbfd6e1c37094b4653f5c2dad65b5 (diff)
downloadglibc-7e625f7e85b4e88f10dbde35a0641742af581806.tar
glibc-7e625f7e85b4e88f10dbde35a0641742af581806.tar.gz
glibc-7e625f7e85b4e88f10dbde35a0641742af581806.tar.bz2
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.
-rw-r--r--ChangeLog42
-rw-r--r--nptl/tst-cond3.c19
-rw-r--r--nptl/tst-eintr1.c16
-rw-r--r--nptl/tst-eintr2.c11
-rw-r--r--nptl/tst-eintr3.c20
-rw-r--r--nptl/tst-eintr4.c20
-rw-r--r--nptl/tst-eintr5.c19
-rw-r--r--nptl/tst-exit2.c10
-rw-r--r--nptl/tst-exit3.c10
-rw-r--r--nptl/tst-mutex6.c17
-rw-r--r--nptl/tst-rwlock5.c14
-rw-r--r--nptl/tst-sem2.c12
-rw-r--r--nptl/tst-spin3.c13
-rw-r--r--nptl/tst-stdio1.c14
-rw-r--r--test-skeleton.c157
15 files changed, 293 insertions, 101 deletions
diff --git a/ChangeLog b/ChangeLog
index a8aae15e70..f6589b4e14 100644
--- 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
diff --git a/nptl/tst-cond3.c b/nptl/tst-cond3.c
index ff904e4378..546564fad0 100644
--- a/nptl/tst-cond3.c
+++ b/nptl/tst-cond3.c
@@ -22,6 +22,10 @@
#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"
diff --git a/nptl/tst-eintr1.c b/nptl/tst-eintr1.c
index 11cd876a74..0946894fbe 100644
--- a/nptl/tst-eintr1.c
+++ b/nptl/tst-eintr1.c
@@ -23,6 +23,11 @@
#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"
diff --git a/nptl/tst-eintr2.c b/nptl/tst-eintr2.c
index 7f50f4bcf4..0ef6d30474 100644
--- a/nptl/tst-eintr2.c
+++ b/nptl/tst-eintr2.c
@@ -24,6 +24,11 @@
#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"
diff --git a/nptl/tst-eintr3.c b/nptl/tst-eintr3.c
index d2c32b970a..f6b2ccf681 100644
--- a/nptl/tst-eintr3.c
+++ b/nptl/tst-eintr3.c
@@ -23,6 +23,11 @@
#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"
diff --git a/nptl/tst-eintr4.c b/nptl/tst-eintr4.c
index 25fae34560..f6d068f334 100644
--- a/nptl/tst-eintr4.c
+++ b/nptl/tst-eintr4.c
@@ -23,6 +23,11 @@
#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"
diff --git a/nptl/tst-eintr5.c b/nptl/tst-eintr5.c
index be6731c798..81f900e8b9 100644
--- a/nptl/tst-eintr5.c
+++ b/nptl/tst-eintr5.c
@@ -24,6 +24,11 @@
#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"
diff --git a/nptl/tst-exit2.c b/nptl/tst-exit2.c
index 3f5ff27b0f..0b7a2caf6a 100644
--- a/nptl/tst-exit2.c
+++ b/nptl/tst-exit2.c
@@ -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"
diff --git a/nptl/tst-exit3.c b/nptl/tst-exit3.c
index da92c82c0e..9481ed9b42 100644
--- a/nptl/tst-exit3.c
+++ b/nptl/tst-exit3.c
@@ -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"
diff --git a/nptl/tst-mutex6.c b/nptl/tst-mutex6.c
index 1940687fee..3e989d8f55 100644
--- a/nptl/tst-mutex6.c
+++ b/nptl/tst-mutex6.c
@@ -23,6 +23,11 @@
#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"
diff --git a/nptl/tst-rwlock5.c b/nptl/tst-rwlock5.c
index b6c5d8a247..20fb471823 100644
--- a/nptl/tst-rwlock5.c
+++ b/nptl/tst-rwlock5.c
@@ -22,6 +22,10 @@
#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"
diff --git a/nptl/tst-sem2.c b/nptl/tst-sem2.c
index 301dde7948..1f609fcf88 100644
--- a/nptl/tst-sem2.c
+++ b/nptl/tst-sem2.c
@@ -17,11 +17,16 @@
<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"
diff --git a/nptl/tst-spin3.c b/nptl/tst-spin3.c
index 8964ecca8b..6cb6f9d48c 100644
--- a/nptl/tst-spin3.c
+++ b/nptl/tst-spin3.c
@@ -21,6 +21,10 @@
#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"
diff --git a/nptl/tst-stdio1.c b/nptl/tst-stdio1.c
index 2d44c16a77..4250e53750 100644
--- a/nptl/tst-stdio1.c
+++ b/nptl/tst-stdio1.c
@@ -21,6 +21,10 @@
#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"
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 */