| #include <pthread.h> | 
 | #include <semaphore.h> | 
 | #include <stdlib.h> | 
 | #include <stdio.h> | 
 | #include <unistd.h> | 
 |  | 
 |  | 
 | static volatile bool destr_called; | 
 | static volatile bool except_caught; | 
 |  | 
 | static pthread_barrier_t b; | 
 |  | 
 |  | 
 | struct monitor | 
 | { | 
 |   // gcc is broken and would generate a warning without this dummy | 
 |   // constructor. | 
 |   monitor () { } | 
 |   ~monitor() { destr_called = true; } | 
 | }; | 
 |  | 
 |  | 
 | static void * | 
 | tf (void *arg) | 
 | { | 
 |   sem_t *s = static_cast<sem_t *> (arg); | 
 |  | 
 |   try | 
 |     { | 
 |       monitor m; | 
 |  | 
 |       pthread_barrier_wait (&b); | 
 |  | 
 |       while (1) | 
 |       sem_wait (s); | 
 |     } | 
 |   catch (...) | 
 |     { | 
 |       except_caught = true; | 
 |       throw; | 
 |     } | 
 |  | 
 |   return NULL; | 
 | } | 
 |  | 
 |  | 
 | static int | 
 | do_test () | 
 | { | 
 |   if (pthread_barrier_init (&b, NULL, 2) != 0) | 
 |     { | 
 |       puts ("barrier_init failed"); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   sem_t s; | 
 |   if (sem_init (&s, 0, 0) != 0) | 
 |     { | 
 |       puts ("sem_init failed"); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   pthread_t th; | 
 |   if (pthread_create (&th, NULL, tf, &s) != 0) | 
 |     { | 
 |       puts ("pthread_create failed"); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   pthread_barrier_wait (&b); | 
 |  | 
 |   /* There is unfortunately no better method to try to assure the | 
 |      child thread reached the sem_wait call and is actually waiting | 
 |      than to sleep here.  */ | 
 |   sleep (1); | 
 |  | 
 |   if (pthread_cancel (th) != 0) | 
 |     { | 
 |       puts ("cancel failed"); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   void *res; | 
 |   if (pthread_join (th, &res) != 0) | 
 |     { | 
 |       puts ("join failed"); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   if (res != PTHREAD_CANCELED) | 
 |     { | 
 |       puts ("thread was not canceled"); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   if (! except_caught) | 
 |     { | 
 |       puts ("exception not caught"); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   if (! destr_called) | 
 |     { | 
 |       puts ("destructor not called"); | 
 |       return 1; | 
 |     } | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | #define TEST_FUNCTION do_test () | 
 | #define TIMEOUT 3 | 
 | #include "../test-skeleton.c" |