don't overwrite io_manager_pipe if it is already set
[ghc.git] / rts / posix / Signals.c
1 /* -----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team, 1998-2005
4 *
5 * Signal processing / handling.
6 *
7 * ---------------------------------------------------------------------------*/
8
9 /* This is non-Posix-compliant.
10 #include "PosixSource.h"
11 */
12 #include "Rts.h"
13 #include "SchedAPI.h"
14 #include "Schedule.h"
15 #include "RtsSignals.h"
16 #include "posix/Signals.h"
17 #include "RtsUtils.h"
18 #include "RtsFlags.h"
19 #include "Prelude.h"
20 #include "ThrIOManager.h"
21
22 #ifdef alpha_HOST_ARCH
23 # if defined(linux_HOST_OS)
24 # include <asm/fpu.h>
25 # else
26 # include <machine/fpu.h>
27 # endif
28 #endif
29
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33
34 #ifdef HAVE_SIGNAL_H
35 # include <signal.h>
36 #endif
37
38 #ifdef HAVE_ERRNO_H
39 # include <errno.h>
40 #endif
41
42 #include <stdlib.h>
43 #include <string.h>
44
45 /* This curious flag is provided for the benefit of the Haskell binding
46 * to POSIX.1 to control whether or not to include SA_NOCLDSTOP when
47 * installing a SIGCHLD handler.
48 */
49 HsInt nocldstop = 0;
50
51 /* -----------------------------------------------------------------------------
52 * The table of signal handlers
53 * -------------------------------------------------------------------------- */
54
55 #if defined(RTS_USER_SIGNALS)
56
57 /* SUP: The type of handlers is a little bit, well, doubtful... */
58 StgInt *signal_handlers = NULL; /* Dynamically grown array of signal handlers */
59 static StgInt nHandlers = 0; /* Size of handlers array */
60
61 static nat n_haskell_handlers = 0;
62
63 /* -----------------------------------------------------------------------------
64 * Allocate/resize the table of signal handlers.
65 * -------------------------------------------------------------------------- */
66
67 static void
68 more_handlers(int sig)
69 {
70 StgInt i;
71
72 if (sig < nHandlers)
73 return;
74
75 if (signal_handlers == NULL)
76 signal_handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
77 else
78 signal_handlers = (StgInt *)stgReallocBytes(signal_handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
79
80 for(i = nHandlers; i <= sig; i++)
81 // Fill in the new slots with default actions
82 signal_handlers[i] = STG_SIG_DFL;
83
84 nHandlers = sig + 1;
85 }
86
87 // Here's the pipe into which we will send our signals
88 static int io_manager_pipe = -1;
89
90 #define IO_MANAGER_WAKEUP 0xff
91 #define IO_MANAGER_DIE 0xfe
92
93 void
94 setIOManagerPipe (int fd)
95 {
96 // only called when THREADED_RTS, but unconditionally
97 // compiled here because GHC.Conc depends on it.
98 if (io_manager_pipe < 0) {
99 io_manager_pipe = fd;
100 }
101 }
102
103 #if defined(THREADED_RTS)
104 void
105 ioManagerWakeup (void)
106 {
107 int r;
108 // Wake up the IO Manager thread by sending a byte down its pipe
109 if (io_manager_pipe >= 0) {
110 StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
111 r = write(io_manager_pipe, &byte, 1);
112 if (r == -1) { sysErrorBelch("ioManagerWakeup: write"); }
113 }
114 }
115
116 void
117 ioManagerDie (void)
118 {
119 int r;
120 // Ask the IO Manager thread to exit
121 if (io_manager_pipe >= 0) {
122 StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
123 r = write(io_manager_pipe, &byte, 1);
124 if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
125 close(io_manager_pipe);
126 io_manager_pipe = -1;
127 }
128 }
129
130 void
131 ioManagerStart (void)
132 {
133 // Make sure the IO manager thread is running
134 Capability *cap;
135 if (io_manager_pipe < 0) {
136 cap = rts_lock();
137 cap = rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);
138 rts_unlock(cap);
139 }
140 }
141 #endif
142
143 #if !defined(THREADED_RTS)
144
145 #define N_PENDING_HANDLERS 16
146
147 siginfo_t pending_handler_buf[N_PENDING_HANDLERS];
148 siginfo_t *next_pending_handler = pending_handler_buf;
149
150 #endif /* THREADED_RTS */
151
152 /* -----------------------------------------------------------------------------
153 * Low-level signal handler
154 *
155 * Places the requested handler on a stack of pending handlers to be
156 * started up at the next context switch.
157 * -------------------------------------------------------------------------- */
158
159 static void
160 generic_handler(int sig USED_IF_THREADS,
161 siginfo_t *info,
162 void *p STG_UNUSED)
163 {
164 #if defined(THREADED_RTS)
165
166 if (io_manager_pipe != -1)
167 {
168 StgWord8 buf[sizeof(siginfo_t) + 1];
169 int r;
170
171 buf[0] = sig;
172 memcpy(buf+1, info, sizeof(siginfo_t));
173 r = write(io_manager_pipe, buf, sizeof(siginfo_t)+1);
174 if (r == -1 && errno == EAGAIN)
175 {
176 errorBelch("lost signal due to full pipe: %d\n", sig);
177 }
178 }
179 // If the IO manager hasn't told us what the FD of the write end
180 // of its pipe is, there's not much we can do here, so just ignore
181 // the signal..
182
183 #else /* not THREADED_RTS */
184
185 /* Can't call allocate from here. Probably can't call malloc
186 either. However, we have to schedule a new thread somehow.
187
188 It's probably ok to request a context switch and allow the
189 scheduler to start the handler thread, but how do we
190 communicate this to the scheduler?
191
192 We need some kind of locking, but with low overhead (i.e. no
193 blocking signals every time around the scheduler).
194
195 Signal Handlers are atomic (i.e. they can't be interrupted), and
196 we can make use of this. We just need to make sure the
197 critical section of the scheduler can't be interrupted - the
198 only way to do this is to block signals. However, we can lower
199 the overhead by only blocking signals when there are any
200 handlers to run, i.e. the set of pending handlers is
201 non-empty.
202 */
203
204 /* We use a stack to store the pending signals. We can't
205 dynamically grow this since we can't allocate any memory from
206 within a signal handler.
207
208 Hence unfortunately we have to bomb out if the buffer
209 overflows. It might be acceptable to carry on in certain
210 circumstances, depending on the signal.
211 */
212
213 memcpy(next_pending_handler, info, sizeof(siginfo_t));
214
215 next_pending_handler++;
216
217 // stack full?
218 if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
219 errorBelch("too many pending signals");
220 stg_exit(EXIT_FAILURE);
221 }
222
223 contextSwitchCapability(&MainCapability);
224
225 #endif /* THREADED_RTS */
226 }
227
228 /* -----------------------------------------------------------------------------
229 * Blocking/Unblocking of the user signals
230 * -------------------------------------------------------------------------- */
231
232 static sigset_t userSignals;
233 static sigset_t savedSignals;
234
235 void
236 initUserSignals(void)
237 {
238 sigemptyset(&userSignals);
239 #ifndef THREADED_RTS
240 getStablePtr((StgPtr)&base_GHCziConc_runHandlers_closure);
241 // needed to keep runHandler alive
242 #endif
243 }
244
245 void
246 blockUserSignals(void)
247 {
248 sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
249 }
250
251 void
252 unblockUserSignals(void)
253 {
254 sigprocmask(SIG_SETMASK, &savedSignals, NULL);
255 }
256
257 rtsBool
258 anyUserHandlers(void)
259 {
260 return n_haskell_handlers != 0;
261 }
262
263 #if !defined(THREADED_RTS)
264 void
265 awaitUserSignals(void)
266 {
267 while (!signals_pending() && sched_state == SCHED_RUNNING) {
268 pause();
269 }
270 }
271 #endif
272
273 /* -----------------------------------------------------------------------------
274 * Install a Haskell signal handler.
275 *
276 * We should really do this in Haskell in GHC.Conc, and share the
277 * signal_handlers array with the one there.
278 *
279 * -------------------------------------------------------------------------- */
280
281 int
282 stg_sig_install(int sig, int spi, void *mask)
283 {
284 sigset_t signals, osignals;
285 struct sigaction action;
286 StgInt previous_spi;
287
288 // Block the signal until we figure out what to do
289 // Count on this to fail if the signal number is invalid
290 if (sig < 0 || sigemptyset(&signals) ||
291 sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
292 return STG_SIG_ERR;
293 }
294
295 more_handlers(sig);
296
297 previous_spi = signal_handlers[sig];
298
299 action.sa_flags = 0;
300
301 switch(spi) {
302 case STG_SIG_IGN:
303 action.sa_handler = SIG_IGN;
304 break;
305
306 case STG_SIG_DFL:
307 action.sa_handler = SIG_DFL;
308 break;
309
310 case STG_SIG_RST:
311 action.sa_flags |= SA_RESETHAND;
312 /* fall through */
313 case STG_SIG_HAN:
314 action.sa_sigaction = generic_handler;
315 action.sa_flags |= SA_SIGINFO;
316 break;
317
318 default:
319 barf("stg_sig_install: bad spi");
320 }
321
322 if (mask != NULL)
323 action.sa_mask = *(sigset_t *)mask;
324 else
325 sigemptyset(&action.sa_mask);
326
327 action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
328
329 if (sigaction(sig, &action, NULL))
330 {
331 errorBelch("sigaction");
332 return STG_SIG_ERR;
333 }
334
335 signal_handlers[sig] = spi;
336
337 switch(spi) {
338 case STG_SIG_RST:
339 case STG_SIG_HAN:
340 sigaddset(&userSignals, sig);
341 if (previous_spi != STG_SIG_HAN && previous_spi != STG_SIG_RST) {
342 n_haskell_handlers++;
343 }
344 break;
345
346 default:
347 sigdelset(&userSignals, sig);
348 if (previous_spi == STG_SIG_HAN || previous_spi == STG_SIG_RST) {
349 n_haskell_handlers--;
350 }
351 break;
352 }
353
354 if (sigprocmask(SIG_SETMASK, &osignals, NULL))
355 {
356 errorBelch("sigprocmask");
357 return STG_SIG_ERR;
358 }
359
360 return previous_spi;
361 }
362
363 /* -----------------------------------------------------------------------------
364 * Creating new threads for signal handlers.
365 * -------------------------------------------------------------------------- */
366
367 #if !defined(THREADED_RTS)
368 void
369 startSignalHandlers(Capability *cap)
370 {
371 siginfo_t *info;
372 int sig;
373
374 blockUserSignals();
375
376 while (next_pending_handler != pending_handler_buf) {
377
378 next_pending_handler--;
379
380 sig = next_pending_handler->si_signo;
381 if (signal_handlers[sig] == STG_SIG_DFL) {
382 continue; // handler has been changed.
383 }
384
385 info = stgMallocBytes(sizeof(siginfo_t), "startSignalHandlers");
386 // freed by runHandler
387 memcpy(info, next_pending_handler, sizeof(siginfo_t));
388
389 scheduleThread (cap,
390 createIOThread(cap,
391 RtsFlags.GcFlags.initialStkSize,
392 rts_apply(cap,
393 rts_apply(cap,
394 &base_GHCziConc_runHandlers_closure,
395 rts_mkPtr(cap, info)),
396 rts_mkInt(cap, info->si_signo))));
397 }
398
399 unblockUserSignals();
400 }
401 #endif
402
403 /* ----------------------------------------------------------------------------
404 * Mark signal handlers during GC.
405 * -------------------------------------------------------------------------- */
406
407 void
408 markSignalHandlers (evac_fn evac STG_UNUSED, void *user STG_UNUSED)
409 {
410 // nothing to do
411 }
412
413 #else /* !RTS_USER_SIGNALS */
414 StgInt
415 stg_sig_install(StgInt sig STG_UNUSED,
416 StgInt spi STG_UNUSED,
417 void* mask STG_UNUSED)
418 {
419 //barf("User signals not supported");
420 return STG_SIG_DFL;
421 }
422
423 #endif
424
425 #if defined(RTS_USER_SIGNALS)
426 /* -----------------------------------------------------------------------------
427 * SIGINT handler.
428 *
429 * We like to shutdown nicely after receiving a SIGINT, write out the
430 * stats, write profiling info, close open files and flush buffers etc.
431 * -------------------------------------------------------------------------- */
432 static void
433 shutdown_handler(int sig STG_UNUSED)
434 {
435 // If we're already trying to interrupt the RTS, terminate with
436 // extreme prejudice. So the first ^C tries to exit the program
437 // cleanly, and the second one just kills it.
438 if (sched_state >= SCHED_INTERRUPTING) {
439 stg_exit(EXIT_INTERRUPTED);
440 } else {
441 interruptStgRts();
442 }
443 }
444
445 /* -----------------------------------------------------------------------------
446 * Install default signal handlers.
447 *
448 * The RTS installs a default signal handler for catching
449 * SIGINT, so that we can perform an orderly shutdown.
450 *
451 * Haskell code may install their own SIGINT handler, which is
452 * fine, provided they're so kind as to put back the old one
453 * when they de-install.
454 *
455 * In addition to handling SIGINT, the RTS also handles SIGFPE
456 * by ignoring it. Apparently IEEE requires floating-point
457 * exceptions to be ignored by default, but alpha-dec-osf3
458 * doesn't seem to do so.
459 * -------------------------------------------------------------------------- */
460 void
461 initDefaultHandlers(void)
462 {
463 struct sigaction action,oact;
464
465 // install the SIGINT handler
466 action.sa_handler = shutdown_handler;
467 sigemptyset(&action.sa_mask);
468 action.sa_flags = 0;
469 if (sigaction(SIGINT, &action, &oact) != 0) {
470 sysErrorBelch("warning: failed to install SIGINT handler");
471 }
472
473 #if defined(HAVE_SIGINTERRUPT)
474 siginterrupt(SIGINT, 1); // isn't this the default? --SDM
475 #endif
476
477 // install the SIGFPE handler
478
479 // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
480 // Apparently IEEE requires floating-point exceptions to be ignored by
481 // default, but alpha-dec-osf3 doesn't seem to do so.
482
483 // Commented out by SDM 2/7/2002: this causes an infinite loop on
484 // some architectures when an integer division by zero occurs: we
485 // don't recover from the floating point exception, and the
486 // program just generates another one immediately.
487 #if 0
488 action.sa_handler = SIG_IGN;
489 sigemptyset(&action.sa_mask);
490 action.sa_flags = 0;
491 if (sigaction(SIGFPE, &action, &oact) != 0) {
492 sysErrorBelch("warning: failed to install SIGFPE handler");
493 }
494 #endif
495
496 #ifdef alpha_HOST_ARCH
497 ieee_set_fp_control(0);
498 #endif
499
500 // ignore SIGPIPE; see #1619
501 action.sa_handler = SIG_IGN;
502 sigemptyset(&action.sa_mask);
503 action.sa_flags = 0;
504 if (sigaction(SIGPIPE, &action, &oact) != 0) {
505 sysErrorBelch("warning: failed to install SIGPIPE handler");
506 }
507 }
508
509 void
510 resetDefaultHandlers(void)
511 {
512 struct sigaction action;
513
514 action.sa_handler = SIG_DFL;
515 sigemptyset(&action.sa_mask);
516 action.sa_flags = 0;
517
518 // restore SIGINT
519 if (sigaction(SIGINT, &action, NULL) != 0) {
520 sysErrorBelch("warning: failed to uninstall SIGINT handler");
521 }
522 // restore SIGPIPE
523 if (sigaction(SIGPIPE, &action, NULL) != 0) {
524 sysErrorBelch("warning: failed to uninstall SIGPIPE handler");
525 }
526 }
527
528 void
529 freeSignalHandlers(void) {
530 if (signal_handlers != NULL) {
531 stgFree(signal_handlers);
532 }
533 }
534
535 #endif /* RTS_USER_SIGNALS */