2 * Signal handling for Plan 9 programs.
3 * We stubbornly use the strings from Plan 9 instead
4 * of the enumerated Unix constants.
5 * There are some weird translations. In particular,
6 * a "kill" note is the same as SIGTERM in Unix.
7 * There is no equivalent note to Unix's SIGKILL, since
8 * it's not a deliverable signal anyway.
10 * We do not handle SIGABRT or SIGSEGV, mainly so that
11 * stack traces show the original source of the signal instead
14 * We have to add some extra entry points to provide the
15 * ability to tweak which signals are deliverable and which
16 * are acted upon. Notifydisable and notifyenable play with
17 * the process signal mask. Notifyignore enables the signal
18 * but will not call notifyf when it comes in. This is occasionally
24 #define NOPLAN9DEFINES
27 extern char *_p9sigstr(int, char*);
28 extern int _p9strsig(char*);
30 typedef struct Sig Sig;
33 int sig; /* signal number */
34 int restart; /* do we restart the system call after this signal is handled? */
35 int enabled; /* is this signal enabled (not masked)? */
36 int notified; /* do we call the notify function for this signal? */
39 /* initial settings; for current status, ask the kernel */
46 /* SIGABRT, 0, 1, 1, */
52 /* SIGSEGV, 0, 1, 1, */
77 for(i=0; i<nelem(sigs); i++)
84 * The thread library initializes _notejmpbuf to its own
85 * routine which provides a per-pthread jump buffer.
86 * If we're not using the thread library, we assume we are
89 typedef struct Jmp Jmp;
103 Jmp *(*_notejmpbuf)(void) = getonejmp;
104 static void noteinit(void);
107 * Actual signal handler.
110 static void (*notifyf)(void*, char*); /* Plan 9 handler */
119 j = (*_notejmpbuf)();
120 switch(p9setjmp(j->b)){
123 (*notifyf)(nil, _p9sigstr(sig, tmp));
125 case 1: /* noted(NDFLT) */
126 if(0)print("DEFAULT %d\n", sig);
127 signal(sig, SIG_DFL);
130 case 2: /* noted(NCONT) */
131 if(0)print("HANDLED %d\n", sig);
145 p9longjmp((*_notejmpbuf)()->b, v==NCONT ? 2 : 1);
151 notify(void (*f)(void*, char*))
165 * Nonsense about enabling and disabling signals.
172 sigaction(s, nil, &sa);
173 return sa.sa_handler;
177 notifysetenable(int sig, int enabled)
185 sigaddset(&mask, sig);
186 sigprocmask(enabled ? SIG_UNBLOCK : SIG_BLOCK, &mask, nil);
190 notifyenable(char *msg)
192 notifyenablex(_p9strsig(msg), 1);
196 notifydisable(char *msg)
198 notifyenablex(_p9strsig(msg), 0);
202 notifyseton(int s, int on)
211 memset(&sa, 0, sizeof sa);
212 sa.sa_handler = on ? signotify : signonotify;
214 sa.sa_flags |= SA_RESTART;
217 * We can't allow signals within signals because there's
218 * only one jump buffer.
220 sigfillset(&sa.sa_mask);
225 sigaction(sig->sig, &sa, nil);
231 notifyseton(_p9strsig(msg), 1);
237 notifysetoff(_p9strsig(msg), 0);
241 * Initialization follows sigs table.
249 for(i=0; i<nelem(sigs); i++){
252 * If someone has already installed a handler,
253 * It's probably some ld preload nonsense,
254 * like pct (a SIGVTALRM-based profiler).
257 if(handler(sig->sig) != SIG_DFL)
260 * Should we only disable and not enable signals?
261 * (I.e. if parent has disabled for us, should we still enable?)
262 * Right now we always initialize to the state we want.
264 notifysetenable(sig->sig, sig->enabled);
265 notifyseton(sig->sig, sig->notified);