test for old pthread_once regression with approximate deadlock check
authorSzabolcs Nagy <nsz@port70.net>
Thu, 8 Aug 2013 18:01:16 +0000 (18:01 +0000)
committerSzabolcs Nagy <nsz@port70.net>
Thu, 8 Aug 2013 18:01:16 +0000 (18:01 +0000)
src/common/print.c
src/regression/pthread_once-deadlock.c [new file with mode: 0644]

index 45a4fd5..b9088ba 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <unistd.h>
+#include "test.h"
 
 volatile int t_status = 0;
 
diff --git a/src/regression/pthread_once-deadlock.c b/src/regression/pthread_once-deadlock.c
new file mode 100644 (file)
index 0000000..28d0d98
--- /dev/null
@@ -0,0 +1,71 @@
+// commit: 7e6be42a77989c01155bdc7333ea58206e1563d4 2011-03-08
+// pthread_once should not deadlock
+#include <pthread.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <string.h>
+#include "test.h"
+
+#define T(f) if ((r=(f))) t_error(#f " failed: %s\n", strerror(r))
+#define E(f) if (f) t_error(#f " failed: %s\n", strerror(errno))
+
+static int count;
+
+static void init(void)
+{
+       count++;
+}
+
+static void *start(void *arg)
+{
+       void **a = arg;
+       int r;
+       E(sem_post(a[1]));
+       T(pthread_once(a[0], init));
+       E(sem_post(a[1]));
+       return 0;
+}
+
+static int deadlocked(sem_t *s)
+{
+       struct timespec ts;
+
+       E(sem_wait(s));
+       E(clock_gettime(CLOCK_REALTIME, &ts));
+       ts.tv_nsec += 100*1000*1000;
+       if (ts.tv_nsec >= 1000*1000*1000) {
+               ts.tv_nsec -= 1000*1000*1000;
+               ts.tv_sec += 1;
+       }
+       errno = 0;
+       E(sem_timedwait(s,&ts));
+       if (errno != ETIMEDOUT)
+               return 0;
+       t_error("pthread_once deadlocked\n");
+       return 1;
+}
+
+int main(void)
+{
+       pthread_t t1,t2,t3;
+       pthread_once_t once = PTHREAD_ONCE_INIT;
+       sem_t s1,s2,s3;
+       void *p;
+       int r;
+
+       E(sem_init(&s1,0,0));
+       E(sem_init(&s2,0,0));
+       E(sem_init(&s3,0,0));
+       T(pthread_create(&t1, 0, start, (void*[]){&once,&s1}));
+       T(pthread_create(&t2, 0, start, (void*[]){&once,&s2}));
+       T(pthread_create(&t3, 0, start, (void*[]){&once,&s3}));
+       if (!deadlocked(&s1)) T(pthread_join(t1,&p));
+       if (!deadlocked(&s2)) T(pthread_join(t2,&p));
+       if (!deadlocked(&s3)) T(pthread_join(t3,&p));
+       if (count != 1)
+               t_error("pthread_once ran init %d times instead of once\n", count);
+       E(sem_destroy(&s1));
+       E(sem_destroy(&s2));
+       E(sem_destroy(&s3));
+       return t_status;
+}