Browse Source

[LibOS] Retry DkObjectsWaitAny on interrupt

DkObjectsWaitAny can be interrupted and return NULL.
Some logic in LibOS was not aware of such behavior.
Isaku Yamahata 5 years ago
parent
commit
0547abf390

+ 2 - 0
LibOS/shim/include/shim_internal.h

@@ -776,6 +776,8 @@ int init_manifest (PAL_HANDLE manifest_handle);
 bool test_user_memory (void * addr, size_t size, bool write);
 bool test_user_string (const char * addr);
 
+int object_wait_with_retry(PAL_HANDLE handle);
+
 #ifdef __x86_64__
 #define switch_stack(stack_top)                                         \
     ({                                                                  \

+ 1 - 1
LibOS/shim/src/Makefile

@@ -51,7 +51,7 @@ objs	= $(addprefix bookkeep/shim_,handle vma thread signal) \
 	  $(addprefix ipc/shim_ipc_,$(ipcns)) \
 	  elf/shim_rtld \
 	  $(addprefix shim_,init table syscalls checkpoint malloc \
-	  async parser debug) syscallas start \
+	  async parser debug object) syscallas start \
 	  $(patsubst %.c,%,$(wildcard sys/*.c))
 graphene_lib = .lib/graphene-lib.a
 pal_lib = $(RUNTIME_DIR)/libpal-$(PAL_HOST).so

+ 1 - 1
LibOS/shim/src/bookkeep/shim_thread.c

@@ -723,7 +723,7 @@ int resume_wrapper (void * param)
     debug_setbuf(tcb, true);
     debug("set tcb to %p\n", libc_tcb);
 
-    DkObjectsWaitAny(1, &thread_start_event, NO_TIMEOUT);
+    object_wait_with_retry(thread_start_event);
 
     restore_context(&tcb->context);
     return 0;

+ 18 - 0
LibOS/shim/src/shim_object.c

@@ -0,0 +1,18 @@
+#include <pal.h>
+#include <shim_internal.h>
+
+int object_wait_with_retry(PAL_HANDLE handle)
+{
+    PAL_HANDLE ret;
+    do {
+        ret = DkObjectsWaitAny(1, &handle, NO_TIMEOUT);
+    } while (ret == NULL && (PAL_NATIVE_ERRNO == PAL_ERROR_INTERRUPTED ||
+                             PAL_NATIVE_ERRNO == PAL_ERROR_TRYAGAIN));
+    if (ret == NULL) {
+        debug("waiting on %p resulted in error %s",
+              handle, PAL_STRERROR(PAL_NATIVE_ERRNO));
+        return -PAL_NATIVE_ERRNO;
+    }
+    assert(ret == handle);
+    return 0;
+}

+ 2 - 2
LibOS/shim/src/sys/shim_clone.c

@@ -97,7 +97,7 @@ int clone_implementation_wrapper(struct clone_args * arg)
     struct clone_args *pcargs = arg;
     int stack_allocated = 0;
 
-    DkObjectsWaitAny(1, &pcargs->create_event, NO_TIMEOUT);
+    object_wait_with_retry(pcargs->create_event);
     DkObjectClose(pcargs->create_event);
 
     struct shim_thread * my_thread = pcargs->thread;
@@ -340,7 +340,7 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
         *set_parent_tid = tid;
 
     DkEventSet(new_args.create_event);
-    DkObjectsWaitAny(1, &new_args.initialize_event, NO_TIMEOUT);
+    object_wait_with_retry(new_args.initialize_event);
     DkObjectClose(new_args.initialize_event);
     put_thread(thread);
     return tid;

+ 1 - 1
LibOS/shim/src/sys/shim_migrate.c

@@ -197,7 +197,7 @@ int join_checkpoint (struct shim_thread * thread, ucontext_t * context,
 
     if (!do_checkpoint) {
         debug("waiting for checkpointing\n");
-        DkObjectsWaitAny(1, &finish_event, NO_TIMEOUT);
+        object_wait_with_retry(finish_event);
         return 0;
     }
 

+ 1 - 1
LibOS/shim/src/sys/shim_semget.c

@@ -859,7 +859,7 @@ unowned:
         }
 
         unlock(hdl->lock);
-        DkObjectsWaitAny(1, &sem->event, NO_TIMEOUT);
+        object_wait_with_retry(sem->event);
         lock(hdl->lock);
         SAVE_PROFILE_INTERVAL(sem_wait_for_complete);
     }

+ 2 - 3
LibOS/shim/src/sys/shim_wait.c

@@ -56,8 +56,7 @@ pid_t shim_do_wait4 (pid_t pid, int * status, int option,
 
         if (!(option & WNOHANG)) {
 block_pid:
-            DkObjectsWaitAny(1, &thread->exit_event,
-                             NO_TIMEOUT);
+            object_wait_with_retry(thread->exit_event);
         }
 
         lock(thread->lock);
@@ -103,7 +102,7 @@ block:
         if (cur->child_exit_event)
             while (listp_empty(&cur->exited_children)) {
                 unlock(cur->lock);
-                DkObjectsWaitAny(1, &cur->child_exit_event, NO_TIMEOUT);
+                object_wait_with_retry(cur->child_exit_event);
                 lock(cur->lock);
             }
     }