This source file includes following definitions.
- findsig
- getonejmp
- signotify
- signonotify
- noted
- notify
- handler
- notesetenable
- noteenable
- notedisable
- notifyseton
- notifyon
- notifyoff
- noteinit
#include <u.h>
#include <signal.h>
#define NOPLAN9DEFINES
#include <libc.h>
extern char *_p9sigstr(int, char*);
extern int _p9strsig(char*);
typedef struct Sig Sig;
struct Sig
{
int sig;
int flags;
};
enum
{
Restart = 1<<0,
Ignore = 1<<1
};
static Sig sigs[] = {
SIGHUP, 0,
SIGINT, 0,
SIGQUIT, 0,
SIGILL, 0,
SIGTRAP, 0,
#ifdef SIGEMT
SIGEMT, 0,
#endif
SIGFPE, 0,
SIGBUS, 0,
SIGCHLD, Restart|Ignore,
SIGSYS, 0,
SIGPIPE, Ignore,
SIGALRM, 0,
SIGTERM, 0,
SIGTSTP, Restart|Ignore,
SIGXCPU, 0,
SIGXFSZ, 0,
SIGVTALRM, 0,
SIGUSR1, 0,
SIGUSR2, 0,
#ifdef SIGWINCH
SIGWINCH, Restart|Ignore,
#endif
#ifdef SIGINFO
SIGINFO, Restart|Ignore,
#endif
};
static Sig*
findsig(int s)
{
int i;
for(i=0; i<nelem(sigs); i++)
if(sigs[i].sig == s)
return &sigs[i];
return nil;
}
typedef struct Jmp Jmp;
struct Jmp
{
p9jmp_buf b;
};
static Jmp onejmp;
static Jmp*
getonejmp(void)
{
return &onejmp;
}
Jmp *(*_notejmpbuf)(void) = getonejmp;
static void noteinit(void);
static void (*notifyf)(void*, char*);
static void
signotify(int sig)
{
char tmp[64];
Jmp *j;
Sig *s;
j = (*_notejmpbuf)();
switch(p9setjmp(j->b)){
case 0:
if(notifyf)
(*notifyf)(nil, _p9sigstr(sig, tmp));
case 1:
if(0)print("DEFAULT %d\n", sig);
s = findsig(sig);
if(s && (s->flags&Ignore))
return;
signal(sig, SIG_DFL);
raise(sig);
_exit(1);
case 2:
if(0)print("HANDLED %d\n", sig);
return;
}
}
static void
signonotify(int sig)
{
USED(sig);
}
int
noted(int v)
{
p9longjmp((*_notejmpbuf)()->b, v==NCONT ? 2 : 1);
abort();
return 0;
}
int
notify(void (*f)(void*, char*))
{
static int init;
notifyf = f;
if(!init){
init = 1;
noteinit();
}
return 0;
}
typedef void Sighandler(int);
static Sighandler*
handler(int s)
{
struct sigaction sa;
sigaction(s, nil, &sa);
return sa.sa_handler;
}
static int
notesetenable(int sig, int enabled)
{
sigset_t mask, omask;
if(sig == 0)
return -1;
sigemptyset(&mask);
sigaddset(&mask, sig);
sigprocmask(enabled ? SIG_UNBLOCK : SIG_BLOCK, &mask, &omask);
return !sigismember(&omask, sig);
}
int
noteenable(char *msg)
{
return notesetenable(_p9strsig(msg), 1);
}
int
notedisable(char *msg)
{
return notesetenable(_p9strsig(msg), 0);
}
static int
notifyseton(int s, int on)
{
Sig *sig;
struct sigaction sa, osa;
sig = findsig(s);
if(sig == nil)
return -1;
memset(&sa, 0, sizeof sa);
sa.sa_handler = on ? signotify : signonotify;
if(sig->flags&Restart)
sa.sa_flags |= SA_RESTART;
sigfillset(&sa.sa_mask);
sigaction(sig->sig, &sa, &osa);
return osa.sa_handler == signotify;
}
int
notifyon(char *msg)
{
return notifyseton(_p9strsig(msg), 1);
}
int
notifyoff(char *msg)
{
return notifyseton(_p9strsig(msg), 0);
}
static void
noteinit(void)
{
int i;
Sig *sig;
for(i=0; i<nelem(sigs); i++){
sig = &sigs[i];
if(handler(sig->sig) != SIG_DFL)
continue;
notifyseton(sig->sig, 1);
}
}