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