From 4c18a59cc3849505282806385e2da0d2e4ab3280 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 2 Sep 2026 13:38:08 -0700 Subject: [PATCH] SIGEV_THREAD timers: block cancellation when operating on semaphores sem_wait is a cancellation point. If the parent thread in timer_create sets td->cancel = 1 before the child thread reaches sem_wait then the thread will exit and sem_post will never be called, causing the parent thread to deadlock in sem_wait. Disable cancellation until after the sem_post. --- src/time/timer_create.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/time/timer_create.c b/src/time/timer_create.c index cc6c2236..a134e935 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -45,6 +45,7 @@ static void *start(void *arg) pthread_t self = __pthread_self(); struct start_args *args = arg; jmp_buf jb; + int cs; void (*notify)(union sigval) = args->sev->sigev_notify_function; union sigval val = args->sev->sigev_value; @@ -53,9 +54,13 @@ static void *start(void *arg) * self->cancel set by the parent if timer creation failed or * self->timer_id if it succeeded, and informs the parent that * we are done accessing the arguments so that the parent can - * proceed past their block lifetime. */ + * proceed past their block lifetime. Disable cancellation, + * if the parent thread cancels this thread before this thread + * calls sem_post it will deadlock. */ + __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); while (sem_wait(&args->sem1)); sem_post(&args->sem2); + __pthread_setcancelstate(cs, 0); if (self->cancel) return 0; -- 2.55.0.979.g7e5102b832-goog