Browse Source

[LibOS] Fix data race between creation/deletion of async helper thread

Data race between creating and exiting the async helper thread: during
async helper thread breaking its while-loop and exiting, another thread
may call install_async_event() and read that the helper is alive, thus
skipping create_async_helper(). Therefore, the other thread installs the
event but there is no async helper thread to trigger it. This commit
fixes this data race by moving check-if-alive under the lock.
Isaku Yamahata 6 years ago
parent
commit
246b9a6fad
1 changed files with 10 additions and 9 deletions
  1. 10 9
      LibOS/shim/src/shim_async.c

+ 10 - 9
LibOS/shim/src/shim_async.c

@@ -173,7 +173,7 @@ static void shim_async_helper(void * arg) {
     PAL_HANDLE install_new_event_hdl = event_handle(&install_new_event);
     object_list[0] = install_new_event_hdl;
 
-    while (async_helper_state == HELPER_ALIVE) {
+    while (true) {
         uint64_t now = DkSystemTimeQuery();
 
         if (polled == install_new_event_hdl) {
@@ -183,6 +183,11 @@ static void shim_async_helper(void * arg) {
         }
 
         lock(&async_helper_lock);
+        if (async_helper_state != HELPER_ALIVE) {
+            async_helper_thread = NULL;
+            unlock(&async_helper_lock);
+            break;
+        }
 
         /* Iterate through all async IO events and alarm/timer events to:
          *   - call callbacks for all triggered events, and
@@ -233,8 +238,6 @@ static void shim_async_helper(void * arg) {
             }
         }
 
-        unlock(&async_helper_lock);
-
         uint64_t sleep_time;
         if (next_expire_time) {
             sleep_time = next_expire_time - now;
@@ -249,20 +252,18 @@ static void shim_async_helper(void * arg) {
         }
 
         if (idle_cycles == MAX_IDLE_CYCLES) {
+            async_helper_state = HELPER_NOTALIVE;
+            async_helper_thread = NULL;
+            unlock(&async_helper_lock);
             debug("Async helper thread has been idle for some time; stopping it\n");
             break;
         }
+        unlock(&async_helper_lock);
 
         /* wait on async IO events + install_new_event + next expiring alarm/timer */
         polled = DkObjectsWaitAny(object_num + 1, object_list, sleep_time);
-        /* ensure that while loop breaks on async_helper_state change */
-        COMPILER_BARRIER();
     }
 
-    lock(&async_helper_lock);
-    async_helper_state = HELPER_NOTALIVE;
-    async_helper_thread = NULL;
-    unlock(&async_helper_lock);
     put_thread(self);
     debug("Async helper thread terminated\n");
     free(object_list);