Introduction
Introduction Statistics Contact Development Disclaimer Help
notify.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
notify.c (4717B)
---
1 /*
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.
9 *
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.
13 *
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
19 * useful.
20 */
21
22 #include <u.h>
23 #include <signal.h>
24 #define NOPLAN9DEFINES
25 #include <libc.h>
26
27 extern char *_p9sigstr(int, char*);
28 extern int _p9strsig(char*);
29
30 typedef struct Sig Sig;
31 struct Sig
32 {
33 int sig; /* signal number */
34 int flags;
35 };
36
37 enum
38 {
39 Restart = 1<<0,
40 Ignore = 1<<1,
41 NoNotify = 1<<2,
42 };
43
44 static Sig sigs[] = {
45 SIGHUP, 0,
46 SIGINT, 0,
47 SIGQUIT, 0,
48 SIGILL, 0,
49 SIGTRAP, 0,
50 /* SIGABRT, 0, */
51 #ifdef SIGEMT
52 SIGEMT, 0,
53 #endif
54 SIGFPE, 0,
55 SIGBUS, 0,
56 /* SIGSEGV, 0, */
57 SIGCHLD, Restart|Ignore,
58 SIGSYS, 0,
59 SIGPIPE, Ignore,
60 SIGALRM, 0,
61 SIGTERM, 0,
62 SIGTSTP, Restart|Ignore|NoNotify,
63 /* SIGTTIN, Restart|Ignore, */
64 /* SIGTTOU, Restart|Ignore, */
65 SIGXCPU, 0,
66 SIGXFSZ, 0,
67 SIGVTALRM, 0,
68 SIGUSR1, 0,
69 SIGUSR2, 0,
70 #ifdef SIGWINCH
71 SIGWINCH, Restart|Ignore|NoNotify,
72 #endif
73 #ifdef SIGINFO
74 SIGINFO, Restart|Ignore|NoNotify,
75 #endif
76 };
77
78 static Sig*
79 findsig(int s)
80 {
81 int i;
82
83 for(i=0; i<nelem(sigs); i++)
84 if(sigs[i].sig == s)
85 return &sigs[i];
86 return nil;
87 }
88
89 /*
90 * The thread library initializes _notejmpbuf to its own
91 * routine which provides a per-pthread jump buffer.
92 * If we're not using the thread library, we assume we are
93 * single-threaded.
94 */
95 typedef struct Jmp Jmp;
96 struct Jmp
97 {
98 p9jmp_buf b;
99 };
100
101 static Jmp onejmp;
102
103 static Jmp*
104 getonejmp(void)
105 {
106 return &onejmp;
107 }
108
109 Jmp *(*_notejmpbuf)(void) = getonejmp;
110 static void noteinit(void);
111
112 /*
113 * Actual signal handler.
114 */
115
116 static void (*notifyf)(void*, char*); /* Plan 9 handler */
117
118 static void
119 signotify(int sig)
120 {
121 char tmp[64];
122 Jmp *j;
123 Sig *s;
124
125 j = (*_notejmpbuf)();
126 switch(p9setjmp(j->b)){
127 case 0:
128 if(notifyf)
129 (*notifyf)(nil, _p9sigstr(sig, tmp));
130 /* fall through */
131 case 1: /* noted(NDFLT) */
132 if(0)print("DEFAULT %d\n", sig);
133 s = findsig(sig);
134 if(s && (s->flags&Ignore))
135 return;
136 signal(sig, SIG_DFL);
137 raise(sig);
138 _exit(1);
139 case 2: /* noted(NCONT) */
140 if(0)print("HANDLED %d\n", sig);
141 return;
142 }
143 }
144
145 static void
146 signonotify(int sig)
147 {
148 USED(sig);
149 }
150
151 int
152 noted(int v)
153 {
154 p9longjmp((*_notejmpbuf)()->b, v==NCONT ? 2 : 1);
155 abort();
156 return 0;
157 }
158
159 int
160 notify(void (*f)(void*, char*))
161 {
162 static int init;
163
164 notifyf = f;
165 if(!init){
166 init = 1;
167 noteinit();
168 }
169 return 0;
170 }
171
172 /*
173 * Nonsense about enabling and disabling signals.
174 */
175 typedef void Sighandler(int);
176 static Sighandler*
177 handler(int s)
178 {
179 struct sigaction sa;
180
181 sigaction(s, nil, &sa);
182 return sa.sa_handler;
183 }
184
185 static int
186 notesetenable(int sig, int enabled)
187 {
188 sigset_t mask, omask;
189
190 if(sig == 0)
191 return -1;
192
193 sigemptyset(&mask);
194 sigaddset(&mask, sig);
195 sigprocmask(enabled ? SIG_UNBLOCK : SIG_BLOCK, &mask, &omask);
196 return !sigismember(&omask, sig);
197 }
198
199 int
200 noteenable(char *msg)
201 {
202 return notesetenable(_p9strsig(msg), 1);
203 }
204
205 int
206 notedisable(char *msg)
207 {
208 return notesetenable(_p9strsig(msg), 0);
209 }
210
211 static int
212 notifyseton(int s, int on)
213 {
214 Sig *sig;
215 struct sigaction sa, osa;
216
217 sig = findsig(s);
218 if(sig == nil)
219 return -1;
220 memset(&sa, 0, sizeof sa);
221 sa.sa_handler = on ? signotify : signonotify;
222 if(sig->flags&Restart)
223 sa.sa_flags |= SA_RESTART;
224
225 /*
226 * We can't allow signals within signals because there's
227 * only one jump buffer.
228 */
229 sigfillset(&sa.sa_mask);
230
231 /*
232 * Install handler.
233 */
234 sigaction(sig->sig, &sa, &osa);
235 return osa.sa_handler == signotify;
236 }
237
238 int
239 notifyon(char *msg)
240 {
241 return notifyseton(_p9strsig(msg), 1);
242 }
243
244 int
245 notifyoff(char *msg)
246 {
247 return notifyseton(_p9strsig(msg), 0);
248 }
249
250 /*
251 * Initialization follows sigs table.
252 */
253 static void
254 noteinit(void)
255 {
256 int i;
257 Sig *sig;
258
259 for(i=0; i<nelem(sigs); i++){
260 sig = &sigs[i];
261 /*
262 * If someone has already installed a handler,
263 * It's probably some ld preload nonsense,
264 * like pct (a SIGVTALRM-based profiler).
265 * Or maybe someone has already called notifyon/notifyof…
266 * Leave it alone.
267 */
268 if(handler(sig->sig) != SIG_DFL)
269 continue;
270 notifyseton(sig->sig, !(sig->flags&NoNotify));
271 }
272 }
273
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.