From 9fac3ad2a05c9025acdad6feae3932711dbcd561 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sun, 8 Mar 2020 14:24:54 +0100 Subject: lib: Fix deadlock in threadpool manager There was a rare deadlock upon destruction of the threadpool manager because the threads were cancelled/joined under lock. Signed-off-by: Dimitri Staessens Signed-off-by: Sander Vrijders --- src/lib/tpm.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/lib/tpm.c b/src/lib/tpm.c index ca2eb1ef..0ba9619b 100644 --- a/src/lib/tpm.c +++ b/src/lib/tpm.c @@ -82,11 +82,19 @@ static void tpm_join(struct tpm * tpm) --tpm->cur; } } + } + list_for_each_safe(p, h, &tpm->pool) { + struct pthr_el * e = list_entry(p, struct pthr_el, next); if (e->kill) { - pthread_join(e->thr, NULL); + pthread_t thr = e->thr; list_del(&e->next); free(e); + pthread_mutex_unlock(&tpm->lock); + + pthread_join(thr, NULL); + + pthread_mutex_lock(&tpm->lock); } } } @@ -256,29 +264,35 @@ static struct pthr_el * tpm_pthr_el(struct tpm * tpm, } - assert(false); - return NULL; } void tpm_inc(struct tpm * tpm) { - pthread_mutex_lock(&tpm->lock); + struct pthr_el * e; - tpm_pthr_el(tpm, pthread_self())->busy = false; + pthread_mutex_lock(&tpm->lock); - --tpm->wrk; + e = tpm_pthr_el(tpm, pthread_self()); + if (e != NULL) { + e->busy = false; + --tpm->wrk; + } pthread_mutex_unlock(&tpm->lock); } void tpm_dec(struct tpm * tpm) { - pthread_mutex_lock(&tpm->lock); + struct pthr_el * e; - tpm_pthr_el(tpm, pthread_self())->busy = true; + pthread_mutex_lock(&tpm->lock); - ++tpm->wrk; + e = tpm_pthr_el(tpm, pthread_self()); + if (e != NULL) { + e->busy = true; + ++tpm->wrk; + } pthread_cond_signal(&tpm->cond); -- cgit v1.2.3