|  | /* Copyright (c) 2013 The Regents of the University of California | 
|  | * Copyright (c) 2015 Google Inc. | 
|  | * Barret Rhoden <brho@cs.berkeley.edu> | 
|  | * Kevin Klues <klueska@cs.berkeley.edu> | 
|  | * See LICENSE for details. | 
|  | */ | 
|  |  | 
|  | #include <errno.h> | 
|  | #include <ros/procinfo.h> | 
|  | #include <ros/syscall.h> | 
|  | #include <parlib/signal.h> | 
|  | #include <parlib/vcore.h> | 
|  | /* This is nasty.  We can't use the regular printf here.  If we do, we'll get | 
|  | * the dreaded "multiple libcs" error during a glibc rebuild.  But we can use an | 
|  | * akaros_printf.  If there are parts of glibc that don't link against parlib, | 
|  | * we'll get the weak symbol.  (rtld perhaps). */ | 
|  | #include <parlib/stdio.h> | 
|  |  | 
|  | /* We define the signal_ops struct in glibc so that it is accessible without | 
|  | * being linked to parlib. Parlib-based 2LSs will override it with their | 
|  | * scheduler specific signal ops. */ | 
|  | struct signal_ops *signal_ops; | 
|  |  | 
|  | /* This is list of sigactions associated with each posix signal. */ | 
|  | static struct sigaction sigactions[_NSIG]; | 
|  |  | 
|  | /* These are the default handlers for each posix signal.  They are listed in | 
|  | * SIGNAL(7) of the Linux Programmer's Manual.  We run them as default | 
|  | * sigactions, instead of the older handlers, so that we have access to the | 
|  | * faulting context. | 
|  | * | 
|  | * Exit codes are set as suggested in the following link.  I wish I could find | 
|  | * the definitive source, but this will have to do for now. | 
|  | * http://unix.stackexchange.com/questions/99112/default-exit-code-when-process-is-terminated | 
|  | * */ | 
|  | static void default_term_handler(int signr, siginfo_t *info, void *ctx) | 
|  | { | 
|  | ros_syscall(SYS_proc_destroy, __procinfo.pid, signr, 0, 0, 0, 0); | 
|  | } | 
|  |  | 
|  | static void default_core_handler(int signr, siginfo_t *info, void *ctx) | 
|  | { | 
|  | akaros_printf("Segmentation Fault on PID %d (sorry, no core dump yet)\n", | 
|  | __procinfo.pid); | 
|  | if (ctx) | 
|  | print_user_context((struct user_context*)ctx); | 
|  | else | 
|  | akaros_printf("No ctx for %s\n", __func__); | 
|  | if (info) { | 
|  | /* ghetto, we don't have access to the PF err, since we only | 
|  | * have a few fields available in siginfo (e.g. there's no | 
|  | * si_trapno). */ | 
|  | akaros_printf("Fault type %d at addr %p\n", info->si_errno, | 
|  | info->si_addr); | 
|  | } else { | 
|  | akaros_printf("No fault info\n"); | 
|  | } | 
|  | default_term_handler((1 << 7) + signr, info, ctx); | 
|  | } | 
|  |  | 
|  | static void default_stop_handler(int signr, siginfo_t *info, void *ctx) | 
|  | { | 
|  | akaros_printf("Stop signal received!  No support to stop yet though!\n"); | 
|  | } | 
|  |  | 
|  | static void default_cont_handler(int signr, siginfo_t *info, void *ctx) | 
|  | { | 
|  | akaros_printf("Cont signal received!  No support to cont yet though!\n"); | 
|  | } | 
|  |  | 
|  | typedef void (*__sigacthandler_t)(int, siginfo_t *, void *); | 
|  | #define SIGACT_ERR	((__sigacthandler_t) -1)	/* Error return.  */ | 
|  | #define SIGACT_DFL	((__sigacthandler_t) 0)		/* Default action.  */ | 
|  | #define SIGACT_IGN	((__sigacthandler_t) 1)		/* Ignore signal.  */ | 
|  |  | 
|  | static __sigacthandler_t default_handlers[] = { | 
|  | [SIGHUP]    = default_term_handler, | 
|  | [SIGINT]    = default_term_handler, | 
|  | [SIGQUIT]   = default_core_handler, | 
|  | [SIGILL]    = default_core_handler, | 
|  | [SIGTRAP]   = default_core_handler, | 
|  | [SIGABRT]   = default_core_handler, | 
|  | [SIGIOT]    = default_core_handler, | 
|  | [SIGBUS]    = default_core_handler, | 
|  | [SIGFPE]    = default_core_handler, | 
|  | [SIGKILL]   = default_term_handler, | 
|  | [SIGUSR1]   = default_term_handler, | 
|  | [SIGSEGV]   = default_core_handler, | 
|  | [SIGUSR2]   = default_term_handler, | 
|  | [SIGPIPE]   = default_term_handler, | 
|  | [SIGALRM]   = default_term_handler, | 
|  | [SIGTERM]   = default_term_handler, | 
|  | [SIGSTKFLT] = default_term_handler, | 
|  | [SIGCHLD]   = SIGACT_IGN, | 
|  | [SIGCONT]   = default_cont_handler, | 
|  | [SIGSTOP]   = default_stop_handler, | 
|  | [SIGTSTP]   = default_stop_handler, | 
|  | [SIGTTIN]   = default_stop_handler, | 
|  | [SIGTTOU]   = default_stop_handler, | 
|  | [SIGURG]    = default_term_handler, | 
|  | [SIGXCPU]   = SIGACT_IGN, | 
|  | [SIGXFSZ]   = default_core_handler, | 
|  | [SIGVTALRM] = default_term_handler, | 
|  | [SIGPROF]   = default_term_handler, | 
|  | [SIGWINCH]  = SIGACT_IGN, | 
|  | [SIGIO]     = default_term_handler, | 
|  | [SIGPWR]    = SIGACT_IGN, | 
|  | [SIGSYS]    = default_core_handler, | 
|  | [SIGSYS+1 ... _NSIG-1] = SIGACT_IGN | 
|  | }; | 
|  |  | 
|  | /* This is the akaros posix signal trigger.  Signals are dispatched from | 
|  | * this function to their proper posix signal handler */ | 
|  | void trigger_posix_signal(int sig_nr, struct siginfo *info, void *aux) | 
|  | { | 
|  | struct sigaction *action; | 
|  |  | 
|  | if (sig_nr >= _NSIG || sig_nr < 0) | 
|  | return; | 
|  | action = &sigactions[sig_nr]; | 
|  | /* Would like a switch/case here, but they are pointers.  We can also | 
|  | * get away with this check early since sa_handler and sa_sigaction are | 
|  | * macros referencing the same union.  The man page isn't specific about | 
|  | * whether or not you need to care about SA_SIGINFO when sending | 
|  | * DFL/ERR/IGN. */ | 
|  | if (action->sa_handler == SIG_ERR) | 
|  | return; | 
|  | if (action->sa_handler == SIG_IGN) | 
|  | return; | 
|  | if (action->sa_handler == SIG_DFL) { | 
|  | if (default_handlers[sig_nr] != SIGACT_IGN) | 
|  | default_handlers[sig_nr](sig_nr, info, aux); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (action->sa_flags & SA_SIGINFO) { | 
|  | /* If NULL info struct passed in, construct our own */ | 
|  | struct siginfo s = {0}; | 
|  |  | 
|  | if (info == NULL) | 
|  | info = &s; | 
|  | /* 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); | 
|  | } | 
|  | } | 
|  |  | 
|  | int __sigaction(int __sig, __const struct sigaction *__restrict __act, | 
|  | struct sigaction *__restrict __oact) | 
|  | { | 
|  | if (__sig <= 0 || __sig >= NSIG) { | 
|  | __set_errno(EINVAL); | 
|  | return -1; | 
|  | } | 
|  | if (__oact) | 
|  | *__oact = sigactions[__sig]; | 
|  | if (!__act) | 
|  | return 0; | 
|  | sigactions[__sig] = *__act; | 
|  | return 0; | 
|  | } | 
|  | libc_hidden_def(__sigaction) | 
|  | weak_alias(__sigaction, sigaction) |