regression test for a race in raise
authorSzabolcs Nagy <nsz@port70.net>
Fri, 9 Aug 2013 01:12:23 +0000 (01:12 +0000)
committerSzabolcs Nagy <nsz@port70.net>
Fri, 9 Aug 2013 01:12:23 +0000 (01:12 +0000)
src/regression/pthread_rwlock-ebusy.c
src/regression/raise-race.c [new file with mode: 0644]

index c2bc2d7..9f157a8 100644 (file)
@@ -11,7 +11,7 @@ static void *tryrdlock(void *arg)
 {
        int r = pthread_rwlock_tryrdlock(arg);
        if (r != EBUSY)
 {
        int r = pthread_rwlock_tryrdlock(arg);
        if (r != EBUSY)
-               t_error("tryrdlock for wrlocked lock returned %s, want EBUSY\n", strerror(errno));
+               t_error("tryrdlock for wrlocked lock returned %s, want EBUSY\n", strerror(r));
        return 0;
 }
 
        return 0;
 }
 
@@ -19,7 +19,7 @@ static void *trywrlock(void *arg)
 {
        int r = pthread_rwlock_trywrlock(arg);
        if (r != EBUSY)
 {
        int r = pthread_rwlock_trywrlock(arg);
        if (r != EBUSY)
-               t_error("trywrlock for rdlocked lock returned %s, want EBUSY\n", strerror(errno));
+               t_error("trywrlock for rdlocked lock returned %s, want EBUSY\n", strerror(r));
        return 0;
 }
 
        return 0;
 }
 
diff --git a/src/regression/raise-race.c b/src/regression/raise-race.c
new file mode 100644 (file)
index 0000000..9b18a8e
--- /dev/null
@@ -0,0 +1,69 @@
+// commit: 370f78f2c80c64b7b0780a01e672494a26b5678e 2011-03-09
+// raise should be robust against forking from a signal handler
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "test.h"
+
+static volatile int c0;
+static volatile int c1;
+static volatile int child;
+
+static void handler0(int sig)
+{
+       c0++;
+}
+
+static void handler1(int sig)
+{
+       c1++;
+       switch (fork()) {
+       case 0: child=1; break;
+       case -1: t_error("fork failed: %s\n", strerror(errno));
+       }
+}
+
+static void *start(void *arg)
+{
+       int i,r,s;
+
+       for (i = 0; i < 1000; i++) {
+               r = raise(SIGRTMIN);
+               if (r)
+                       t_error("raise failed: %s\n", strerror(errno));
+       }
+       if (c0 != 1000)
+               t_error("lost signals: got %d, wanted 1000 (ischild %d forks %d)\n", c0, child, c1);
+       if (child)
+               _exit(t_status);
+
+       /* make sure we got all pthread_kills, then wait the forked children */
+       while (c1 < 100);
+       for (i = 0; i < 100; i++) {
+               r = wait(&s);
+               if (r == -1)
+                       t_error("wait failed: %s\n", strerror(errno));
+               else if (!WIFEXITED(s) || WTERMSIG(s))
+                       t_error("child failed: pid:%d status:%d\n", r, s);
+       }
+       return 0;
+}
+
+int main(void)
+{
+       pthread_t t;
+       void *p;
+       int r, i, s;
+
+       signal(SIGRTMIN, handler0);
+       signal(SIGRTMIN+1, handler1);
+
+       pthread_create(&t, 0, start, 0);
+       for (i = 0; i < 100; i++)
+               pthread_kill(t, SIGRTMIN+1);
+       pthread_join(t,&p);
+       return t_status;
+}