#include <pthreadP.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> static pthread_barrier_t b; static pthread_t th2; static void * tf2 (void *arg) { sigset_t mask; if (pthread_sigmask (SIG_SETMASK, NULL, &mask) != 0) { puts ("pthread_sigmask failed"); exit (1); } if (sigismember (&mask, SIGCANCEL)) { puts ("SIGCANCEL blocked in new thread"); exit (1); } /* Sync with the main thread so that we do not test anything else. */ int e = pthread_barrier_wait (&b); if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("barrier_wait failed"); exit (1); } while (1) { /* Just a cancelable call. */ struct timespec ts = { 10000, 0 }; nanosleep (&ts, 0); } return NULL; } static void unwhand (void *arg) { if (pthread_create (&th2, NULL, tf2, NULL) != 0) { puts ("unwhand: create failed"); exit (1); } } static void * tf (void *arg) { pthread_cleanup_push (unwhand, NULL); /* Sync with the main thread so that we do not test anything else. */ int e = pthread_barrier_wait (&b); if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("barrier_wait failed"); exit (1); } while (1) { /* Just a cancelable call. */ struct timespec ts = { 10000, 0 }; nanosleep (&ts, 0); } pthread_cleanup_pop (0); return NULL; } static int do_test (void) { if (pthread_barrier_init (&b, NULL, 2) != 0) { puts ("barrier_init failed"); return 1; } pthread_t th1; if (pthread_create (&th1, NULL, tf, NULL) != 0) { puts ("create failed"); return 1; } int e = pthread_barrier_wait (&b); if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("barrier_wait failed"); return 1; } /* Make sure tf1 enters nanosleep. */ struct timespec ts = { 0, 500000000 }; while (nanosleep (&ts, &ts) != 0) ; if (pthread_cancel (th1) != 0) { puts ("1st cancel failed"); return 1; } void *res; if (pthread_join (th1, &res) != 0) { puts ("1st join failed"); return 1; } if (res != PTHREAD_CANCELED) { puts ("1st thread not canceled"); return 1; } e = pthread_barrier_wait (&b); if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("barrier_wait failed"); return 1; } /* Make sure tf2 enters nanosleep. */ ts.tv_sec = 0; ts.tv_nsec = 500000000; while (nanosleep (&ts, &ts) != 0) ; puts ("calling pthread_cancel the second time"); if (pthread_cancel (th2) != 0) { puts ("2nd cancel failed"); return 1; } puts ("calling pthread_join the second time"); if (pthread_join (th2, &res) != 0) { puts ("2nd join failed"); return 1; } if (res != PTHREAD_CANCELED) { puts ("2nd thread not canceled"); return 1; } if (pthread_barrier_destroy (&b) != 0) { puts ("barrier_destroy failed"); return 0; } return 0; } #define TEST_FUNCTION do_test () #define TIMEOUT 4 #include "../test-skeleton.c"