From 11dcfc5e044f55941ffd3f1155bbda51ed05aff7 Mon Sep 17 00:00:00 2001 From: hewenliang Date: Mon, 12 Aug 2019 22:30:20 +0000 Subject: [PATCH] urcu: fix deadlock issue using SIG_RCU reason: 1.use a seperate thread(cds_lfht_workqueue) to handle hash table auto resize, and this thread block all signal at initialization. 2.While in urcu-signal flavor, call_rcu_thread will send SIGRCU signal to all the registed thread to make them do cmm_smp_mb. 3.Based on above, call_rcu_thread and workqueue thread will trapped into a dead loop: where call_rcu_thread hold the rcu_registry_lock to waiting all the registed thread to do cmm_smp_mb, while workqueue thread nerver do cmm_smp_mb and waiting to get rcu_registry_lock to unregiter from rcu. so we should not block SIGRCU in workqueue thread to avoid the dead lock. Signed-off-by: hewenliang --- src/rculfhash.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/rculfhash.c b/src/rculfhash.c index fed33e4..fc3d610 100644 --- a/src/rculfhash.c +++ b/src/rculfhash.c @@ -273,6 +273,7 @@ #include #include #include +#include #include #include #include @@ -2112,7 +2113,7 @@ static void cds_lfht_worker_init(struct urcu_workqueue *workqueue, { int ret; sigset_t mask; - + sigset_t set; /* Block signal for entire process, so only our thread processes it. */ ret = sigfillset(&mask); if (ret) @@ -2120,6 +2121,11 @@ static void cds_lfht_worker_init(struct urcu_workqueue *workqueue, ret = pthread_sigmask(SIG_BLOCK, &mask, NULL); if (ret) urcu_die(ret); + sigemptyset(&set); + sigaddset(&set, SIGRCU); + ret = pthread_sigmask(SIG_UNBLOCK, &set, NULL); + if (ret) + urcu_die(ret); } static void cds_lfht_init_worker(const struct rcu_flavor_struct *flavor) -- 2.19.1