blob: da075d719a8215bb2580a6a06834cc31f006aef8 [file] [log] [blame]
#include <u.h>
#include <signal.h>
#define NOPLAN9DEFINES
#include <libc.h>
extern char *_p9sigstr(int, char*);
static struct {
int sig;
int restart;
int dumb;
} sigs[] = {
SIGHUP, 0, 0,
SIGINT, 0, 0,
SIGQUIT, 0, 0,
SIGILL, 0, 0,
SIGTRAP, 0, 0,
/* SIGABRT, */
#ifdef SIGEMT
SIGEMT, 0, 0,
#endif
SIGFPE, 0, 0,
SIGBUS, 0, 0,
/* SIGSEGV, */
SIGCHLD, 1, 1,
SIGSYS, 0, 0,
SIGPIPE, 0, 1,
SIGALRM, 0, 0,
SIGTERM, 0, 0,
SIGTSTP, 1, 1,
SIGTTIN, 1, 1,
SIGTTOU, 1, 1,
SIGXCPU, 0, 0,
SIGXFSZ, 0, 0,
SIGVTALRM, 0, 0,
SIGUSR1, 0, 0,
SIGUSR2, 0, 0,
SIGWINCH, 1, 1,
#ifdef SIGINFO
SIGINFO, 0, 0,
#endif
};
typedef struct Jmp Jmp;
struct Jmp
{
p9jmp_buf b;
};
static Jmp onejmp;
static Jmp*
getonejmp(void)
{
return &onejmp;
}
Jmp *(*_notejmpbuf)(void) = getonejmp;
static void (*notifyf)(void*, char*);
static int alldumb;
static void
nop(int sig)
{
USED(sig);
}
static void
notifysigf(int sig)
{
int v;
char tmp[64];
Jmp *j;
j = (*_notejmpbuf)();
v = p9setjmp(j->b);
if(v == 0 && notifyf)
(*notifyf)(nil, _p9sigstr(sig, tmp));
else if(v == 2){
if(0)print("HANDLED %d\n", sig);
return;
}
if(0)print("DEFAULT %d\n", sig);
signal(sig, SIG_DFL);
raise(sig);
}
int
noted(int v)
{
p9longjmp((*_notejmpbuf)()->b, v==NCONT ? 2 : 1);
abort();
return 0;
}
static void
handlesig(int s, int r, int skip)
{
struct sigaction sa, osa;
/*
* If someone has already installed a handler,
* It's probably some ld preload nonsense,
* like pct (a SIGVTALRM-based profiler).
* Leave it alone.
*/
sigaction(s, nil, &osa);
if(osa.sa_handler != SIG_DFL && osa.sa_handler != notifysigf && osa.sa_handler != nop)
return;
memset(&sa, 0, sizeof sa);
if(skip)
sa.sa_handler = nop;
else if(notifyf == 0)
sa.sa_handler = SIG_DFL;
else
sa.sa_handler = notifysigf;
/*
* We assume that one jump buffer per thread
* is okay, which means that we can't deal with
* signal handlers called during signal handlers.
*/
sigfillset(&sa.sa_mask);
if(r)
sa.sa_flags |= SA_RESTART;
else
sa.sa_flags &= ~SA_RESTART;
sigaction(s, &sa, nil);
}
int
notify(void (*f)(void*, char*))
{
int i;
notifyf = f;
for(i=0; i<nelem(sigs); i++)
handlesig(sigs[i].sig, sigs[i].restart, sigs[i].dumb && !alldumb);
return 0;
}
void
notifyall(int all)
{
int i;
alldumb = all;
for(i=0; i<nelem(sigs); i++)
if(sigs[i].dumb)
handlesig(sigs[i].sig, sigs[i].restart, !all);
}
void
notifyatsig(int sig, int use)
{
int i;
for(i=0; i<nelem(sigs); i++)
if(sigs[i].sig == sig)
handlesig(sigs[i].sig, sigs[i].restart, 0);
}