From: Mathieu Desnoyers Date: Wed, 17 May 2017 22:36:54 +0000 (-0400) Subject: Fix: thread exit vs futex wait/wakeup race X-Git-Tag: v2.8.7~10 X-Git-Url: https://git.liburcu.org/?p=lttng-tools.git;a=commitdiff_plain;h=212a7c5ffa425113159ddf0190c2b65d75c03615 Fix: thread exit vs futex wait/wakeup race relayd_live_stop performs, in this order: CMM_STORE_SHARED(live_dispatch_thread_exit, 1); [A] futex_nto1_wake(&viewer_conn_queue.futex); [B] whereas thread_dispatcher does: while (!CMM_LOAD_SHARED(live_dispatch_thread_exit)) { [1] [...] futex_nto1_prepare(&viewer_conn_queue.futex); [2] [...] futex_nto1_wait(&viewer_conn_queue.futex); [3] Unfortunately, on the following sequence: [1] [A] [B] [2] [3] thread_dispatcher will end up hanging. We need to move the live_dispatch_thread_exit load between "prepare" and "wait" to fix this. There are similar scenarios with relay_thread_dispatcher, and the session daemon thread_dispatch_ust_registration, which are also fixed here. Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- diff --git a/src/bin/lttng-relayd/live.c b/src/bin/lttng-relayd/live.c index cc88032dc..ffec5977e 100644 --- a/src/bin/lttng-relayd/live.c +++ b/src/bin/lttng-relayd/live.c @@ -654,12 +654,16 @@ void *thread_dispatcher(void *data) health_code_update(); - while (!CMM_LOAD_SHARED(live_dispatch_thread_exit)) { + for (;;) { health_code_update(); /* Atomically prepare the queue futex */ futex_nto1_prepare(&viewer_conn_queue.futex); + if (CMM_LOAD_SHARED(live_dispatch_thread_exit)) { + break; + } + do { health_code_update(); diff --git a/src/bin/lttng-relayd/main.c b/src/bin/lttng-relayd/main.c index 56efaae34..9c96af127 100644 --- a/src/bin/lttng-relayd/main.c +++ b/src/bin/lttng-relayd/main.c @@ -969,12 +969,16 @@ static void *relay_thread_dispatcher(void *data) health_code_update(); - while (!CMM_LOAD_SHARED(dispatch_thread_exit)) { + for (;;) { health_code_update(); /* Atomically prepare the queue futex */ futex_nto1_prepare(&relay_conn_queue.futex); + if (CMM_LOAD_SHARED(dispatch_thread_exit)) { + break; + } + do { health_code_update(); diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c index 8527ad04c..50eead010 100644 --- a/src/bin/lttng-sessiond/main.c +++ b/src/bin/lttng-sessiond/main.c @@ -1916,12 +1916,16 @@ static void *thread_dispatch_ust_registration(void *data) DBG("[thread] Dispatch UST command started"); - while (!CMM_LOAD_SHARED(dispatch_thread_exit)) { + for (;;) { health_code_update(); /* Atomically prepare the queue futex */ futex_nto1_prepare(&ust_cmd_queue.futex); + if (CMM_LOAD_SHARED(dispatch_thread_exit)) { + break; + } + do { struct ust_app *app = NULL; ust_cmd = NULL;