114 lines
1.7 KiB
C++
114 lines
1.7 KiB
C++
#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"
|