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 because
11 * the thread library queues its notes for later, and we want
12 * to dump core with the state at time of delivery.
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 */
56 SIGCHLD, Restart|Ignore,
61 SIGTSTP, Restart|Ignore,
62 SIGTTIN, Restart|Ignore,
63 SIGTTOU, Restart|Ignore,
69 SIGWINCH, Restart|Ignore,
71 SIGINFO, Restart|Ignore,
80 for(i=0; i<nelem(sigs); i++)
87 * The thread library initializes _notejmpbuf to its own
88 * routine which provides a per-pthread jump buffer.
89 * If we're not using the thread library, we assume we are
92 typedef struct Jmp Jmp;
106 Jmp *(*_notejmpbuf)(void) = getonejmp;
107 static void noteinit(void);
110 * Actual signal handler.
113 static void (*notifyf)(void*, char*); /* Plan 9 handler */
122 j = (*_notejmpbuf)();
123 switch(p9setjmp(j->b)){
126 (*notifyf)(nil, _p9sigstr(sig, tmp));
128 case 1: /* noted(NDFLT) */
129 if(0)print("DEFAULT %d\n", sig);
131 if(s && (s->flags&Ignore))
133 signal(sig, SIG_DFL);
136 case 2: /* noted(NCONT) */
137 if(0)print("HANDLED %d\n", sig);
151 p9longjmp((*_notejmpbuf)()->b, v==NCONT ? 2 : 1);
157 notify(void (*f)(void*, char*))
170 * Nonsense about enabling and disabling signals.
172 typedef void Sighandler(int);
178 sigaction(s, nil, &sa);
179 return sa.sa_handler;
183 notesetenable(int sig, int enabled)
185 sigset_t mask, omask;
191 sigaddset(&mask, sig);
192 sigprocmask(enabled ? SIG_UNBLOCK : SIG_BLOCK, &mask, &omask);
193 return !sigismember(&omask, sig);
197 noteenable(char *msg)
199 return notesetenable(_p9strsig(msg), 1);
203 notedisable(char *msg)
205 return notesetenable(_p9strsig(msg), 0);
209 notifyseton(int s, int on)
212 struct sigaction sa, osa;
217 memset(&sa, 0, sizeof sa);
218 sa.sa_handler = on ? signotify : signonotify;
219 if(sig->flags&Restart)
220 sa.sa_flags |= SA_RESTART;
223 * We can't allow signals within signals because there's
224 * only one jump buffer.
226 sigfillset(&sa.sa_mask);
231 sigaction(sig->sig, &sa, &osa);
232 return osa.sa_handler == signotify;
238 return notifyseton(_p9strsig(msg), 1);
244 return notifyseton(_p9strsig(msg), 0);
248 * Initialization follows sigs table.
256 for(i=0; i<nelem(sigs); i++){
259 * If someone has already installed a handler,
260 * It's probably some ld preload nonsense,
261 * like pct (a SIGVTALRM-based profiler).
262 * Or maybe someone has already called notifyon/notifyoff.
265 if(handler(sig->sig) != SIG_DFL)
267 notifyseton(sig->sig, 1);