| 
					
				 | 
			
			
				@@ -32,6 +32,16 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <pal.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <asm/signal.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// __rt_sighandler_t is different from __sighandler_t in <asm-generic/signal-defs.h>: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    typedef void __signalfn_t(int); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//    typedef __signalfn_t *__sighandler_t 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+typedef void (*__rt_sighandler_t)(int, siginfo_t*, void*); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static __rt_sighandler_t default_sighandler[NUM_SIGS]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static struct shim_signal ** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 allocate_signal_log (struct shim_thread * thread, int sig) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -594,23 +604,9 @@ __sigset_t * set_sig_mask (struct shim_thread * thread, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return &thread->signal_mask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void (*default_sighandler[NUM_SIGS]) (int, siginfo_t *, void *); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-__handle_one_signal (shim_tcb_t * tcb, int sig, struct shim_signal * signal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    struct shim_thread * thread = (struct shim_thread *) tcb->tp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    struct shim_signal_handle * sighdl = &thread->signal_handles[sig - 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void (*handler) (int, siginfo_t *, void *) = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (signal->info.si_signo == SIGCP) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        join_checkpoint(thread, SI_CP_SESSION(&signal->info)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    debug("%s handled\n", signal_name(sig)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    lock(&thread->lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static __rt_sighandler_t __get_sighandler(struct shim_thread* thread, int sig) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    struct shim_signal_handle* sighdl = &thread->signal_handles[sig - 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    __rt_sighandler_t handler = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (sighdl->action) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         struct __kernel_sigaction * act = sighdl->action; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -622,24 +618,40 @@ __handle_one_signal (shim_tcb_t * tcb, int sig, struct shim_signal * signal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #ifdef __i386__ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 # error "x86-32 support is heavily broken." 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        handler = (void *)act->k_sa_handler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        handler = (void*)act->k_sa_handler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (act->sa_flags & SA_RESETHAND) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             sighdl->action = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             free(act); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    unlock(&thread->lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if ((void*)handler == SIG_IGN) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return handler ? : default_sighandler[sig - 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+__handle_one_signal(shim_tcb_t* tcb, int sig, struct shim_signal* signal) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    struct shim_thread* thread = (struct shim_thread*)tcb->tp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    __rt_sighandler_t handler = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if ((void *) handler == (void *) 1) /* SIG_IGN */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (signal->info.si_signo == SIGCP) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        join_checkpoint(thread, SI_CP_SESSION(&signal->info)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!handler && !(handler = default_sighandler[sig - 1])) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lock(&thread->lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    handler = __get_sighandler(thread, sig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    unlock(&thread->lock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!handler) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /* if the context is never stored in the signal, it means the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       signal is handled during system calls, and before the thread 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       is resumed. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    debug("%s handled\n", signal_name(sig)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // If the context is never stored in the signal, it means the signal is handled during 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // system calls, and before the thread is resumed. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!signal->context_stored) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         __store_context(tcb, NULL, signal); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -661,8 +673,7 @@ __handle_one_signal (shim_tcb_t * tcb, int sig, struct shim_signal * signal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         memcpy(&tcb->context, context, sizeof(struct shim_context)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (signal->pal_context) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        memcpy(signal->pal_context, signal->context.uc_mcontext.gregs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-               sizeof(PAL_CONTEXT)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        memcpy(signal->pal_context, signal->context.uc_mcontext.gregs, sizeof(PAL_CONTEXT)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void __handle_signal (shim_tcb_t * tcb, int sig) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -717,9 +728,17 @@ void handle_signal (void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     debug("__enable_preempt: %s:%d\n", __FILE__, __LINE__); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void append_signal (struct shim_thread * thread, int sig, siginfo_t * info, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    bool wakeup) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// Need to hold thread->lock when calling this function 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void append_signal(struct shim_thread* thread, int sig, siginfo_t* info, bool need_interrupt) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    __rt_sighandler_t handler = __get_sighandler(thread, sig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!handler) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // SIGSTOP and SIGKILL cannot be ignored 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        assert(sig != SIGSTOP && sig != SIGKILL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // If a signal is set to be ignored, append the signal but don't interrupt the thread 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        need_interrupt = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     struct shim_signal * signal = malloc(sizeof(struct shim_signal)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!signal) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -736,7 +755,7 @@ void append_signal (struct shim_thread * thread, int sig, siginfo_t * info, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (signal_log) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         *signal_log = signal; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (wakeup) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (need_interrupt) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             debug("resuming thread %u\n", thread->tid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             thread_wakeup(thread); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             DkThreadResume(thread->pal_handle); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -777,8 +796,7 @@ static void sighandler_core (int sig, siginfo_t * info, void * ucontext) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sighandler_kill(sig, info, ucontext); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void (*default_sighandler[NUM_SIGS]) (int, siginfo_t *, void *) = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static __rt_sighandler_t default_sighandler[NUM_SIGS] = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /* SIGHUP */    &sighandler_kill, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /* SIGINT */    &sighandler_kill, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /* SIGQUIT */   &sighandler_core, 
			 |