diff --git a/src/regression/pthread_cond_wait-cancel_ignored.c b/src/regression/pthread_cond_wait-cancel_ignored.c new file mode 100644 index 0000000..6d02bb9 --- /dev/null +++ b/src/regression/pthread_cond_wait-cancel_ignored.c @@ -0,0 +1,54 @@ +// commit 76ca7a5446a8aec2b671a401d5e1878c4704754e +// pthread_cond_wait should act on cancellation arriving after unlocking mutex + +#include +#include +#include + +#include "test.h" + +static pthread_mutex_t mx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t cv = PTHREAD_COND_INITIALIZER; +static int waiting; + +static void cleanup(void *p) +{ + waiting = 0; + pthread_cond_signal(&cv); + pthread_mutex_unlock(&mx); +} + +static void *waiter(void *p) +{ + pthread_mutex_lock(&mx); + waiting = 1; + pthread_cond_signal(&cv); + pthread_cleanup_push(cleanup, 0); + while (waiting) pthread_cond_wait(&cv, &mx); + pthread_cleanup_pop(1); + return 0; +} + +int main(void) +{ + pthread_t td; + struct timespec ts; + void *rv; + pthread_mutex_lock(&mx); + pthread_create(&td, 0, waiter, 0); + while (!waiting) pthread_cond_wait(&cv, &mx); + pthread_cancel(td); + clock_gettime(CLOCK_REALTIME, &ts); + if ((ts.tv_nsec+=30000000) >= 1000000000) { + ts.tv_sec++; + ts.tv_nsec -= 1000000000; + } + while (waiting && !pthread_cond_timedwait(&cv, &mx, &ts)); + waiting = 0; + pthread_cond_signal(&cv); + pthread_mutex_unlock(&mx); + pthread_join(td, &rv); + if (rv != PTHREAD_CANCELED) + t_error("pthread_cond_wait did not act on cancellation\n"); + return t_status; +}