Fix: thread exit vs futex wait/wakeup race
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 17 May 2017 22:36:54 +0000 (18:36 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 19 May 2017 20:46:21 +0000 (16:46 -0400)
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 <mathieu.desnoyers@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-relayd/live.c
src/bin/lttng-relayd/main.c
src/bin/lttng-sessiond/main.c

index 9e1085f33615018237a4acd2abd434c2362c265b..f9d57281eea812fe0052dd052921539eb6fe5ee5 100644 (file)
@@ -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();
 
index 919c5a96a7a2baa1680febd84ccb9e225fa3a386..8a183db28d226a0b25d924889a4ac9ed2715e11a 100644 (file)
@@ -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();
 
index 0df0b1f2e04bc4601149088740b6feec2b0bfdb2..44b88f39f5c89808ea0c02832b563a6644cd3a53 100644 (file)
@@ -1868,12 +1868,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;
This page took 0.03057 seconds and 4 git commands to generate.