diff options
author | Alexey Izbyshev <izbyshev@ispras.ru> | 2022-09-08 12:18:56 +0300 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2022-09-19 13:24:05 -0400 |
commit | 3ad3fa962efee12067d68c3405a537dce156a7ac (patch) | |
tree | 9e10fc277ba0851e2132bb3cc92a0d4738eea4aa | |
parent | bf14ef193b4203aa9a8b173faeeea06d98397f65 (diff) | |
download | musl-3ad3fa962efee12067d68c3405a537dce156a7ac.tar.gz musl-3ad3fa962efee12067d68c3405a537dce156a7ac.tar.xz musl-3ad3fa962efee12067d68c3405a537dce156a7ac.zip |
fix thread leak on timer_create(SIGEV_THREAD) failure
After commit 5b74eed3b301e2227385f3bf26d3bb7c2d822cf8 the timer thread doesn't check whether timer_create() actually created the timer, proceeding to wait for a signal that might never arrive. We can't fix this by simply checking for a negative timer_id after pthread_barrier_wait() because we have no way to distinguish a timer creation failure and a request to delete a timer with INT_MAX id if it happens to arrive quickly (a variation of this bug existed before 5b74eed3b301e2227385f3bf26d3bb7c2d822cf8, where the timer would be leaked in this case). So (ab)use cancel field of pthread_t instead.
-rw-r--r-- | src/time/timer_create.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/src/time/timer_create.c b/src/time/timer_create.c index 4bef2390..cd32c945 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -43,6 +43,8 @@ static void *start(void *arg) union sigval val = args->sev->sigev_value; pthread_barrier_wait(&args->b); + if (self->cancel) + return 0; for (;;) { siginfo_t si; while (sigwaitinfo(SIGTIMER_SET, &si) < 0); @@ -113,8 +115,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict ksev.sigev_signo = SIGTIMER; ksev.sigev_notify = SIGEV_THREAD_ID; ksev.sigev_tid = td->tid; - if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) + if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) { timerid = -1; + td->cancel = 1; + } td->timer_id = timerid; pthread_barrier_wait(&args.b); if (timerid < 0) return -1; |