Add default page fault handling to map to SIGSEGV in pthreads
authorKevin Klues <klueska@cs.berkeley.edu>
Tue, 11 Mar 2014 18:42:16 +0000 (11:42 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Tue, 11 Mar 2014 18:42:16 +0000 (11:42 -0700)
I refactored the signal handling code a bit so that page faults in our
pthread library trigger SIGSEGV signals that application code can
handle.

user/parlib/include/parlib.h
user/parlib/signal.c
user/pthread/pthread.c

index 11b8ace..11f69c2 100644 (file)
@@ -14,6 +14,7 @@
 #include <ros/syscall.h>
 #include <ros/procinfo.h>
 #include <ros/procdata.h>
+#include <signal.h>
 #include <stdint.h>
 #include <errno.h>
 #include <ros_debug.h>
@@ -58,6 +59,7 @@ int         sys_abort_sysc(struct syscall *sysc);
 long           syscall_async(struct syscall *sysc, unsigned long num, ...);
 
 void           init_posix_signals(void);       /* in signal.c */
+void           trigger_posix_signal(int sig_nr, struct siginfo *info, void *aux);
 #ifdef __cplusplus
 }
 #endif
index 119b351..f88003a 100644 (file)
@@ -51,16 +51,16 @@ static void default_term_handler(int signr)
 }
 static void default_core_handler(int signr)
 {
-       fprintf(stderr, "Segmentation Fault (sorry, no core dump yet)");
+       fprintf(stderr, "Segmentation Fault (sorry, no core dump yet)\n");
        default_term_handler((1 << 7) + signr);
 }
 static void default_stop_handler(int signr)
 {
-       fprintf(stderr, "Stop signal received!  No support to stop yet though!");
+       fprintf(stderr, "Stop signal received!  No support to stop yet though!\n");
 }
 static void default_cont_handler(int signr)
 {
-       fprintf(stderr, "Cont signal received!  No support to cont yet though!");
+       fprintf(stderr, "Cont signal received!  No support to cont yet though!\n");
 }
 static __sighandler_t default_handlers[] = {
        [SIGHUP]    = default_term_handler, 
@@ -97,16 +97,12 @@ static __sighandler_t default_handlers[] = {
        [SIGSYS]    = default_core_handler
 };
 
-/* This is the catch all akaros event->posix signal handler.  All posix signals
- * are received in a single akaros event type.  They are then dispatched from
+
+/* This is the akaros posix signal trigger.  Signals are dispatched from
  * this function to their proper posix signal handler */
-static void handle_posix_signal(struct event_msg *ev_msg, unsigned int ev_type)
+void trigger_posix_signal(int sig_nr, struct siginfo *info, void *aux)
 {
-       int sig_nr;
        struct sigaction *action;
-       struct siginfo info = {0};
-       assert(ev_msg);
-       sig_nr = ev_msg->ev_arg1;
        if (sig_nr > _NSIG - 1 || sig_nr < 0)
                return;
        action = &sigactions[sig_nr];
@@ -124,19 +120,38 @@ static void handle_posix_signal(struct event_msg *ev_msg, unsigned int ev_type)
        }
 
        if (action->sa_flags & SA_SIGINFO) {
-               info.si_signo = sig_nr;
-               /* TODO: consider pid and whatnot */
-               action->sa_sigaction(sig_nr, &info, 0);
+               /* Make sure the caller either already set singo in the info struct, or
+                * if they didn't, make sure it has been zeroed out (i.e. not just some
+                * garbage on the stack. */
+               assert(info->si_signo == sig_nr || info->si_signo == 0);
+               info->si_signo = sig_nr;
+               /* TODO: consider info->pid and whatnot */
+               /* We assume that this function follows the proper calling convention
+                * (i.e. it wasn't written in some crazy assembly function that
+                * trashes all its registers, i.e GO's default runtime handler) */
+               action->sa_sigaction(sig_nr, info, aux);
        } else {
                action->sa_handler(sig_nr);
        }
 }
 
+/* This is the catch all akaros event->posix signal handler.  All posix signals
+ * are received in a single akaros event type.  They are then dispatched from
+ * this function to their proper posix signal handler */
+static void handle_event(struct event_msg *ev_msg, unsigned int ev_type)
+{
+       int sig_nr;
+       struct siginfo info = {0};
+       assert(ev_msg);
+       sig_nr = ev_msg->ev_arg1;
+       trigger_posix_signal(sig_nr, &info, 0);
+}
+
 /* Called from uthread_slim_init() */
 void init_posix_signals(void)
 {
        struct event_queue *posix_sig_ev_q;
-       ev_handlers[EV_POSIX_SIGNAL] = handle_posix_signal;
+       ev_handlers[EV_POSIX_SIGNAL] = handle_event;
        posix_sig_ev_q = get_big_event_q();
        assert(posix_sig_ev_q);
        posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_FALLBACK;
@@ -216,7 +231,7 @@ int sigtimedwait(__const sigset_t *__restrict __set,
        return 0;
 }
 
-/* Needs support with handle_posix_signal to deal with passing values with POSIX
+/* Needs support with trigger_posix_signal to deal with passing values with POSIX
  * signals. */
 int sigqueue(__pid_t __pid, int __sig, __const union sigval __val)
 {
index a1eafb2..ed99a64 100644 (file)
@@ -275,10 +275,17 @@ void pth_thread_refl_fault(struct uthread *uthread, unsigned int trap_nr,
        }
 
        if (!(err & PF_VMR_BACKED)) {
-               /* TODO: put your SIGSEGV handling here */
-               printf("Pthread page faulted outside a VMR\n");
-               print_user_context(&uthread->u_ctx);
-               exit(-1);
+               struct siginfo info = {0};
+               info.si_code = SEGV_MAPERR;
+               info.si_addr = (void*)aux;
+
+               int vcoreid = vcore_id();
+               void *temp_tls_desc = get_tls_desc(vcoreid);
+               set_tls_desc(uthread->tls_desc, vcore_id());
+               trigger_posix_signal(SIGSEGV, &info, &uthread->u_ctx);
+               set_tls_desc(temp_tls_desc, vcoreid);
+               pth_thread_runnable(uthread);
+               return;
        }
        /* stitching for the event handler.  sysc -> uth, uth -> sysc */
        uthread->local_sysc.u_data = uthread;