1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
/*
* rocks/signal.c
*
* Signal setup and interposition.
*
* Copyright (C) 2001 Victor Zandy
* See COPYING for distribution terms.
*/
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include "rs.h"
#include "log.h"
static sigset_t rs_handled; /* signals used by rocks */
static sigset_t ap_handled; /* signals used by application */
static struct sigaction rsh[NSIG]; /* signal action set by rocks */
static struct sigaction app[NSIG]; /* signal action set by application */
static struct sigaction def[NSIG]; /* default signal action */
static void
death(int sig)
{
rs_log("suicide: signal %d", sig);
assert(0);
}
static void
handle(int sig, siginfo_t *info, void *ctx)
{
if (sigismember(&rs_handled, sig))
rsh[sig].sa_sigaction(sig, info, ctx);
if (sigismember(&ap_handled, sig)) {
rs_log("passing signal %d to application handler", sig);
rs_mode_push(RS_MODE_RS);
if (app[sig].sa_flags & (SA_ONESHOT|SA_RESETHAND))
sigdelset(&ap_handled, sig);
app[sig].sa_sigaction(sig, info, ctx);
rs_mode_pop();
rs_log("returning from application signal %d handler", sig);
}
if (sig == SIGSEGV) {
while (1)
;
}
}
/* for rocks handlers */
void
rs_rs_sigaction(int sig, const struct sigaction *sa)
{
sigaddset(&rs_handled, sig);
rsh[sig] = *sa;
}
int
rs_sigaction(int sig, const struct sigaction *act, struct sigaction *oldact)
{
int was;
was = sigismember(&ap_handled, sig);
if (oldact)
*oldact = was ? app[sig] : def[sig];
if (act) {
if (act->sa_handler != SIG_DFL
&& act->sa_handler != SIG_IGN
&& sig != SIGALRM) {
sigaddset(&ap_handled, sig);
app[sig] = *act;
}
if (was && (act->sa_handler == SIG_DFL
|| act->sa_handler == SIG_IGN))
sigdelset(&ap_handled, sig);
}
return 0;
}
int
rs___libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oldact)
{
return rs_sigaction(sig, act, oldact);
}
sighandler_t
rs_signal(int sig, sighandler_t handler)
{
struct sigaction sa, old;
sa.sa_handler = handler;
sa.sa_flags = SA_ONESHOT|SA_NOMASK;
rs_sigaction(sig, &sa, &old);
return (old.sa_flags & SA_SIGINFO)
? old.sa_handler : (sighandler_t) old.sa_sigaction;
}
int
rs_sigprocmask(int how, const sigset_t *iset, sigset_t *oldset)
{
int i;
sigset_t set;
memcpy(&set, iset, sizeof(set));
if (how == SIG_BLOCK || how == SIG_SETMASK)
for (i = 1; i < NSIG; i++)
if (sigismember(&rs_handled, i))
sigdelset(&rs_handled, i);
return sigprocmask(how, &set, oldset);
}
int
rs_sigsuspend(const sigset_t *mask)
{
int i;
sigset_t set;
memcpy(&set, mask, sizeof(set));
for (i = 1; i < NSIG; i++)
if (sigismember(&rs_handled, i))
sigdelset(&rs_handled, i);
return sigsuspend(&set);
}
int
rs_sigaltstack(const stack_t *ss, stack_t *oss)
{
assert(!oss);
return 0;
}
unsigned int
rs_alarm(unsigned int t)
{
/* We ignore application alarms;
FIXME handle application alarms */
return 0;
}
void
rs_init_signal()
{
int i;
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_RESTART|SA_SIGINFO;
sa.sa_sigaction = handle;
sigemptyset(&sa.sa_mask);
for (i = 1; i < NSIG; i++) {
if (i == SIGKILL
|| i == SIGSTOP
|| i == SIGINT
|| i == SIGTERM)
continue;
if (0 > sigaction(i, &sa, &def[i]))
assert(0);
}
sigemptyset(&rs_handled);
sigemptyset(&ap_handled);
sigfillset(&sa.sa_mask);
sigdelset(&sa.sa_mask, SIGTERM);
sigdelset(&sa.sa_mask, SIGINT);
sa.sa_flags = SA_RESTART|SA_SIGINFO;
sa.sa_handler = death;
rs_rs_sigaction(SIGPIPE, &sa);
rs_rs_sigaction(SIGBUS, &sa);
}
|