Blob
1 #include <u.h>2 #include <signal.h>3 #define NOPLAN9DEFINES4 #include <libc.h>6 extern char *_p9sigstr(int, char*);8 static struct {9 int sig;10 int restart;11 int dumb;12 } sigs[] = {13 SIGHUP, 0, 0,14 SIGINT, 0, 0,15 SIGQUIT, 0, 0,16 SIGILL, 0, 0,17 SIGTRAP, 0, 0,18 /* SIGABRT, */19 #ifdef SIGEMT20 SIGEMT, 0, 0,21 #endif22 SIGFPE, 0, 0,23 SIGBUS, 0, 0,24 /* SIGSEGV, */25 SIGCHLD, 1, 1,26 SIGSYS, 0, 0,27 SIGPIPE, 0, 1,28 SIGALRM, 0, 0,29 SIGTERM, 0, 0,30 SIGTSTP, 1, 1,31 SIGTTIN, 1, 1,32 SIGTTOU, 1, 1,33 SIGXCPU, 0, 0,34 SIGXFSZ, 0, 0,35 SIGVTALRM, 0, 0,36 SIGUSR1, 0, 0,37 SIGUSR2, 0, 0,38 SIGWINCH, 1, 1,39 #ifdef SIGINFO40 SIGINFO, 0, 0,41 #endif42 };44 typedef struct Jmp Jmp;45 struct Jmp46 {47 p9jmp_buf b;48 };50 static Jmp onejmp;52 static Jmp*53 getonejmp(void)54 {55 return &onejmp;56 }58 Jmp *(*_notejmpbuf)(void) = getonejmp;59 static void (*notifyf)(void*, char*);60 static int alldumb;62 static void63 nop(int sig)64 {65 USED(sig);66 }68 static void69 notifysigf(int sig)70 {71 int v;72 char tmp[64];73 Jmp *j;75 j = (*_notejmpbuf)();76 v = p9setjmp(j->b);77 if(v == 0 && notifyf)78 (*notifyf)(nil, _p9sigstr(sig, tmp));79 else if(v == 2){80 if(0)print("HANDLED %d\n", sig);81 return;82 }83 if(0)print("DEFAULT %d\n", sig);84 signal(sig, SIG_DFL);85 raise(sig);86 }88 int89 noted(int v)90 {91 p9longjmp((*_notejmpbuf)()->b, v==NCONT ? 2 : 1);92 abort();93 return 0;94 }96 static void97 handlesig(int s, int r, int skip)98 {99 struct sigaction sa, osa;101 /*102 * If someone has already installed a handler,103 * It's probably some ld preload nonsense,104 * like pct (a SIGVTALRM-based profiler).105 * Leave it alone.106 */107 sigaction(s, nil, &osa);108 if(osa.sa_handler != SIG_DFL && osa.sa_handler != notifysigf && osa.sa_handler != nop)109 return;111 memset(&sa, 0, sizeof sa);112 if(skip)113 sa.sa_handler = nop;114 else if(notifyf == 0)115 sa.sa_handler = SIG_DFL;116 else117 sa.sa_handler = notifysigf;119 /*120 * We assume that one jump buffer per thread121 * is okay, which means that we can't deal with122 * signal handlers called during signal handlers.123 */124 sigfillset(&sa.sa_mask);125 if(r)126 sa.sa_flags |= SA_RESTART;127 else128 sa.sa_flags &= ~SA_RESTART;129 sigaction(s, &sa, nil);130 }132 int133 notify(void (*f)(void*, char*))134 {135 int i;137 notifyf = f;138 for(i=0; i<nelem(sigs); i++)139 handlesig(sigs[i].sig, sigs[i].restart, sigs[i].dumb && !alldumb);140 return 0;141 }143 void144 notifyall(int all)145 {146 int i;148 alldumb = all;149 for(i=0; i<nelem(sigs); i++)150 if(sigs[i].dumb)151 handlesig(sigs[i].sig, sigs[i].restart, !all);152 }154 void155 notifyatsig(int sig, int use)156 {157 int i;159 for(i=0; i<nelem(sigs); i++)160 if(sigs[i].sig == sig)161 handlesig(sigs[i].sig, sigs[i].restart, 0);162 }