summaryrefslogtreecommitdiff
path: root/src/lib/tpm.c
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2020-03-08 14:24:54 +0100
committerSander Vrijders <sander@ouroboros.rocks>2020-03-14 15:38:14 +0100
commit9fac3ad2a05c9025acdad6feae3932711dbcd561 (patch)
tree5e9cc92ecf060856c2b89d3d1042592bdedc2b93 /src/lib/tpm.c
parentfe6b60909d455abdac7885ceaba1097749e7aeb1 (diff)
downloadouroboros-9fac3ad2a05c9025acdad6feae3932711dbcd561.tar.gz
ouroboros-9fac3ad2a05c9025acdad6feae3932711dbcd561.zip
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 <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/lib/tpm.c')
-rw-r--r--src/lib/tpm.c32
1 files 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);