Improvements to shutting down of the runtime
[ghc-hetmet.git] / ghc / 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
20 #ifdef alpha_HOST_ARCH
21 # if defined(linux_HOST_OS)
22 #  include <asm/fpu.h>
23 # else
24 #  include <machine/fpu.h>
25 # endif
26 #endif
27
28 #ifdef HAVE_UNISTD_H
29 # include <unistd.h>
30 #endif
31
32 #ifdef HAVE_SIGNAL_H
33 # include <signal.h>
34 #endif
35
36 #include <stdlib.h>
37
38 /* This curious flag is provided for the benefit of the Haskell binding
39  * to POSIX.1 to control whether or not to include SA_NOCLDSTOP when
40  * installing a SIGCHLD handler. 
41  */
42 StgInt nocldstop = 0;
43
44 /* -----------------------------------------------------------------------------
45  * The table of signal handlers
46  * -------------------------------------------------------------------------- */
47
48 #if defined(RTS_USER_SIGNALS)
49
50 /* SUP: The type of handlers is a little bit, well, doubtful... */
51 StgInt *signal_handlers = NULL; /* Dynamically grown array of signal handlers */
52 static StgInt nHandlers = 0;    /* Size of handlers array */
53
54 static nat n_haskell_handlers = 0;
55
56 /* -----------------------------------------------------------------------------
57  * Allocate/resize the table of signal handlers.
58  * -------------------------------------------------------------------------- */
59
60 static void
61 more_handlers(I_ sig)
62 {
63     StgInt i;
64
65     if (sig < nHandlers)
66         return;
67
68     if (signal_handlers == NULL)
69         signal_handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
70     else
71         signal_handlers = (StgInt *)stgReallocBytes(signal_handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
72
73     for(i = nHandlers; i <= sig; i++)
74         // Fill in the new slots with default actions
75         signal_handlers[i] = STG_SIG_DFL;
76
77     nHandlers = sig + 1;
78 }
79
80 /* -----------------------------------------------------------------------------
81  * Pending Handlers
82  *
83  * The mechanism for starting handlers differs between the threaded
84  * (THREADED_RTS) and non-threaded versions of the RTS.
85  *
86  * When the RTS is single-threaded, we just write the pending signal
87  * handlers into a buffer, and start a thread for each one in the
88  * scheduler loop.
89  *
90  * When THREADED_RTS, the problem is that signals might be
91  * delivered to multiple threads, so we would need to synchronise
92  * access to pending_handler_buf somehow.  Using thread
93  * synchronisation from a signal handler isn't possible in general
94  * (some OSs support it, eg. MacOS X, but not all).  So instead:
95  *
96  *   - the signal handler writes the signal number into the pipe
97  *     managed by the IO manager thread (see GHC.Conc).
98  *   - the IO manager picks up the signal number and calls
99  *     startSignalHandler() to start the thread.
100  *
101  * This also has the nice property that we don't need to arrange to
102  * wake up a worker task to start the signal handler: the IO manager
103  * wakes up when we write into the pipe.
104  *
105  * -------------------------------------------------------------------------- */
106
107 // Here's the pipe into which we will send our signals
108 static int io_manager_pipe = -1;
109
110 void
111 setIOManagerPipe (int fd)
112 {
113     // only called when THREADED_RTS, but unconditionally
114     // compiled here because GHC.Conc depends on it.
115     io_manager_pipe = fd;
116 }
117
118 #if !defined(THREADED_RTS)
119
120 #define N_PENDING_HANDLERS 16
121
122 StgPtr pending_handler_buf[N_PENDING_HANDLERS];
123 StgPtr *next_pending_handler = pending_handler_buf;
124
125 #endif /* THREADED_RTS */
126
127 /* -----------------------------------------------------------------------------
128  * SIGCONT handler
129  *
130  * It seems that shells tend to put stdin back into blocking mode
131  * following a suspend/resume of the process.  Here we arrange to put
132  * it back into non-blocking mode.  We don't do anything to
133  * stdout/stderr because these handles don't get put into non-blocking
134  * mode at all - see the comments on stdout/stderr in PrelHandle.hsc.
135  * -------------------------------------------------------------------------- */
136
137 static void
138 cont_handler(int sig STG_UNUSED)
139 {
140     setNonBlockingFd(0);
141 }
142
143 /* -----------------------------------------------------------------------------
144  * Low-level signal handler
145  *
146  * Places the requested handler on a stack of pending handlers to be
147  * started up at the next context switch.
148  * -------------------------------------------------------------------------- */
149
150 static void
151 generic_handler(int sig)
152 {
153     sigset_t signals;
154
155 #if defined(THREADED_RTS)
156
157     if (io_manager_pipe != -1)
158     {
159         // Write the signal number into the pipe as a single byte.  We
160         // hope that signals fit into a byte...
161         StgWord8 csig = (StgWord8)sig;
162         write(io_manager_pipe, &csig, 1);
163     }
164     // If the IO manager hasn't told us what the FD of the write end
165     // of its pipe is, there's not much we can do here, so just ignore
166     // the signal..
167
168 #else /* not THREADED_RTS */
169
170     /* Can't call allocate from here.  Probably can't call malloc
171        either.  However, we have to schedule a new thread somehow.
172
173        It's probably ok to request a context switch and allow the
174        scheduler to  start the handler thread, but how do we
175        communicate this to the scheduler?
176
177        We need some kind of locking, but with low overhead (i.e. no
178        blocking signals every time around the scheduler).
179        
180        Signal Handlers are atomic (i.e. they can't be interrupted), and
181        we can make use of this.  We just need to make sure the
182        critical section of the scheduler can't be interrupted - the
183        only way to do this is to block signals.  However, we can lower
184        the overhead by only blocking signals when there are any
185        handlers to run, i.e. the set of pending handlers is
186        non-empty.
187     */
188        
189     /* We use a stack to store the pending signals.  We can't
190        dynamically grow this since we can't allocate any memory from
191        within a signal handler.
192
193        Hence unfortunately we have to bomb out if the buffer
194        overflows.  It might be acceptable to carry on in certain
195        circumstances, depending on the signal.  
196     */
197
198     *next_pending_handler++ = deRefStablePtr((StgStablePtr)signal_handlers[sig]);
199
200     // stack full?
201     if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
202         errorBelch("too many pending signals");
203         stg_exit(EXIT_FAILURE);
204     }
205     
206 #endif /* THREADED_RTS */
207
208     // re-establish the signal handler, and carry on
209     sigemptyset(&signals);
210     sigaddset(&signals, sig);
211     sigprocmask(SIG_UNBLOCK, &signals, NULL);
212
213     // *always* do the SIGCONT handler, even if the user overrides it.
214     if (sig == SIGCONT) {
215         cont_handler(sig);
216     }
217
218     context_switch = 1;
219 }
220
221 /* -----------------------------------------------------------------------------
222  * Blocking/Unblocking of the user signals
223  * -------------------------------------------------------------------------- */
224
225 static sigset_t userSignals;
226 static sigset_t savedSignals;
227
228 void
229 initUserSignals(void)
230 {
231     sigemptyset(&userSignals);
232 }
233
234 void
235 blockUserSignals(void)
236 {
237     sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
238 }
239
240 void
241 unblockUserSignals(void)
242 {
243     sigprocmask(SIG_SETMASK, &savedSignals, NULL);
244 }
245
246 rtsBool
247 anyUserHandlers(void)
248 {
249     return n_haskell_handlers != 0;
250 }
251
252 #if !defined(THREADED_RTS)
253 void
254 awaitUserSignals(void)
255 {
256     while (!signals_pending() && sched_state == SCHED_RUNNING) {
257         pause();
258     }
259 }
260 #endif
261
262 /* -----------------------------------------------------------------------------
263  * Install a Haskell signal handler.
264  * -------------------------------------------------------------------------- */
265
266 int
267 stg_sig_install(int sig, int spi, StgStablePtr *handler, void *mask)
268 {
269     sigset_t signals, osignals;
270     struct sigaction action;
271     StgInt previous_spi;
272
273     // Block the signal until we figure out what to do
274     // Count on this to fail if the signal number is invalid
275     if (sig < 0 || sigemptyset(&signals) ||
276         sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
277         return STG_SIG_ERR;
278     }
279     
280     more_handlers(sig);
281
282     previous_spi = signal_handlers[sig];
283
284     action.sa_flags = 0;
285     
286     switch(spi) {
287     case STG_SIG_IGN:
288         signal_handlers[sig] = STG_SIG_IGN;
289         sigdelset(&userSignals, sig);
290         action.sa_handler = SIG_IGN;
291         break;
292         
293     case STG_SIG_DFL:
294         signal_handlers[sig] = STG_SIG_DFL;
295         sigdelset(&userSignals, sig);
296         action.sa_handler = SIG_DFL;
297         break;
298
299     case STG_SIG_HAN:
300     case STG_SIG_RST:
301         signal_handlers[sig] = (StgInt)*handler;
302         sigaddset(&userSignals, sig);
303         action.sa_handler = generic_handler;
304         if (spi == STG_SIG_RST) {
305             action.sa_flags = SA_RESETHAND;
306         }
307         n_haskell_handlers++;
308         break;
309
310     default:
311         barf("stg_sig_install: bad spi");
312     }
313
314     if (mask != NULL)
315         action.sa_mask = *(sigset_t *)mask;
316     else
317         sigemptyset(&action.sa_mask);
318
319     action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
320
321     if (sigaction(sig, &action, NULL) || 
322         sigprocmask(SIG_SETMASK, &osignals, NULL)) 
323     {
324         // need to return an error code, so avoid a stable pointer leak
325         // by freeing the previous handler if there was one.
326         if (previous_spi >= 0) {
327             freeStablePtr(stgCast(StgStablePtr,signal_handlers[sig]));
328             n_haskell_handlers--;
329         }
330         return STG_SIG_ERR;
331     }
332
333     if (previous_spi == STG_SIG_DFL || previous_spi == STG_SIG_IGN
334         || previous_spi == STG_SIG_ERR) {
335         return previous_spi;
336     } else {
337         *handler = (StgStablePtr)previous_spi;
338         return STG_SIG_HAN;
339     }
340 }
341
342 /* -----------------------------------------------------------------------------
343  * Creating new threads for signal handlers.
344  * -------------------------------------------------------------------------- */
345
346 #if !defined(THREADED_RTS)
347 void
348 startSignalHandlers(Capability *cap)
349 {
350   blockUserSignals();
351   
352   while (next_pending_handler != pending_handler_buf) {
353
354     next_pending_handler--;
355
356     scheduleThread (cap,
357         createIOThread(cap,
358                        RtsFlags.GcFlags.initialStkSize, 
359                        (StgClosure *) *next_pending_handler));
360   }
361
362   unblockUserSignals();
363 }
364 #endif
365
366 /* ----------------------------------------------------------------------------
367  * Mark signal handlers during GC.
368  *
369  * We do this rather than trying to start all the signal handlers
370  * prior to GC, because that requires extra heap for the new threads.
371  * Signals must be blocked (see blockUserSignals() above) during GC to
372  * avoid race conditions.
373  * -------------------------------------------------------------------------- */
374
375 #if !defined(THREADED_RTS)
376 void
377 markSignalHandlers (evac_fn evac)
378 {
379     StgPtr *p;
380
381     p = next_pending_handler;
382     while (p != pending_handler_buf) {
383         p--;
384         evac((StgClosure **)p);
385     }
386 }
387 #else
388 void
389 markSignalHandlers (evac_fn evac STG_UNUSED)
390 {
391 }
392 #endif
393
394 #else /* !RTS_USER_SIGNALS */
395 StgInt 
396 stg_sig_install(StgInt sig STG_UNUSED,
397                 StgInt spi STG_UNUSED,
398                 StgStablePtr* handler STG_UNUSED,
399                 void* mask STG_UNUSED)
400 {
401   //barf("User signals not supported");
402   return STG_SIG_DFL;
403 }
404
405 #endif
406
407 #if defined(RTS_USER_SIGNALS)
408 /* -----------------------------------------------------------------------------
409  * SIGINT handler.
410  *
411  * We like to shutdown nicely after receiving a SIGINT, write out the
412  * stats, write profiling info, close open files and flush buffers etc.
413  * -------------------------------------------------------------------------- */
414 #ifdef SMP
415 pthread_t startup_guy;
416 #endif
417
418 static void
419 shutdown_handler(int sig STG_UNUSED)
420 {
421 #ifdef SMP
422     // if I'm a worker thread, send this signal to the guy who
423     // originally called startupHaskell().  Since we're handling
424     // the signal, it won't be a "send to all threads" type of signal
425     // (according to the POSIX threads spec).
426     if (pthread_self() != startup_guy) {
427         pthread_kill(startup_guy, sig);
428         return;
429     }
430 #endif
431
432     // If we're already trying to interrupt the RTS, terminate with
433     // extreme prejudice.  So the first ^C tries to exit the program
434     // cleanly, and the second one just kills it.
435     if (sched_state >= SCHED_INTERRUPTING) {
436         stg_exit(EXIT_INTERRUPTED);
437     } else {
438         interruptStgRts();
439     }
440 }
441
442 /* -----------------------------------------------------------------------------
443  * Install default signal handlers.
444  *
445  * The RTS installs a default signal handler for catching
446  * SIGINT, so that we can perform an orderly shutdown.
447  *
448  * Haskell code may install their own SIGINT handler, which is
449  * fine, provided they're so kind as to put back the old one
450  * when they de-install.
451  *
452  * In addition to handling SIGINT, the RTS also handles SIGFPE
453  * by ignoring it.  Apparently IEEE requires floating-point
454  * exceptions to be ignored by default, but alpha-dec-osf3
455  * doesn't seem to do so.
456  * -------------------------------------------------------------------------- */
457 void
458 initDefaultHandlers()
459 {
460     struct sigaction action,oact;
461
462 #ifdef SMP
463     startup_guy = pthread_self();
464 #endif
465
466     // install the SIGINT handler
467     action.sa_handler = shutdown_handler;
468     sigemptyset(&action.sa_mask);
469     action.sa_flags = 0;
470     if (sigaction(SIGINT, &action, &oact) != 0) {
471         errorBelch("warning: failed to install SIGINT handler");
472     }
473
474 #if defined(HAVE_SIGINTERRUPT)
475     siginterrupt(SIGINT, 1);    // isn't this the default? --SDM
476 #endif
477
478     // install the SIGCONT handler
479     action.sa_handler = cont_handler;
480     sigemptyset(&action.sa_mask);
481     action.sa_flags = 0;
482     if (sigaction(SIGCONT, &action, &oact) != 0) {
483         errorBelch("warning: failed to install SIGCONT handler");
484     }
485
486     // install the SIGFPE handler
487
488     // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
489     // Apparently IEEE requires floating-point exceptions to be ignored by
490     // default, but alpha-dec-osf3 doesn't seem to do so.
491
492     // Commented out by SDM 2/7/2002: this causes an infinite loop on
493     // some architectures when an integer division by zero occurs: we
494     // don't recover from the floating point exception, and the
495     // program just generates another one immediately.
496 #if 0
497     action.sa_handler = SIG_IGN;
498     sigemptyset(&action.sa_mask);
499     action.sa_flags = 0;
500     if (sigaction(SIGFPE, &action, &oact) != 0) {
501         errorBelch("warning: failed to install SIGFPE handler");
502     }
503 #endif
504
505 #ifdef alpha_HOST_ARCH
506     ieee_set_fp_control(0);
507 #endif
508 }
509
510 #endif /* RTS_USER_SIGNALS */