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