| /* 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) |