036411f8bfef679e403b87d457f845ad9260be64
[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() && !interrupted) {
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(void)
349 {
350   blockUserSignals();
351   
352   while (next_pending_handler != pending_handler_buf) {
353
354     next_pending_handler--;
355
356     scheduleThread (
357         &MainCapability,
358         createIOThread(&MainCapability, 
359                        RtsFlags.GcFlags.initialStkSize, 
360                        (StgClosure *) *next_pending_handler));
361   }
362
363   unblockUserSignals();
364 }
365 #endif
366
367 /* ----------------------------------------------------------------------------
368  * Mark signal handlers during GC.
369  *
370  * We do this rather than trying to start all the signal handlers
371  * prior to GC, because that requires extra heap for the new threads.
372  * Signals must be blocked (see blockUserSignals() above) during GC to
373  * avoid race conditions.
374  * -------------------------------------------------------------------------- */
375
376 #if !defined(THREADED_RTS)
377 void
378 markSignalHandlers (evac_fn evac)
379 {
380     StgPtr *p;
381
382     p = next_pending_handler;
383     while (p != pending_handler_buf) {
384         p--;
385         evac((StgClosure **)p);
386     }
387 }
388 #else
389 void
390 markSignalHandlers (evac_fn evac STG_UNUSED)
391 {
392 }
393 #endif
394
395 #else /* !RTS_USER_SIGNALS */
396 StgInt 
397 stg_sig_install(StgInt sig STG_UNUSED,
398                 StgInt spi STG_UNUSED,
399                 StgStablePtr* handler STG_UNUSED,
400                 void* mask STG_UNUSED)
401 {
402   //barf("User signals not supported");
403   return STG_SIG_DFL;
404 }
405
406 #endif
407
408 #if defined(RTS_USER_SIGNALS)
409 /* -----------------------------------------------------------------------------
410  * SIGINT handler.
411  *
412  * We like to shutdown nicely after receiving a SIGINT, write out the
413  * stats, write profiling info, close open files and flush buffers etc.
414  * -------------------------------------------------------------------------- */
415 #ifdef SMP
416 pthread_t startup_guy;
417 #endif
418
419 static void
420 shutdown_handler(int sig STG_UNUSED)
421 {
422 #ifdef SMP
423     // if I'm a worker thread, send this signal to the guy who
424     // originally called startupHaskell().  Since we're handling
425     // the signal, it won't be a "send to all threads" type of signal
426     // (according to the POSIX threads spec).
427     if (pthread_self() != startup_guy) {
428         pthread_kill(startup_guy, sig);
429         return;
430     }
431 #endif
432
433     // If we're already trying to interrupt the RTS, terminate with
434     // extreme prejudice.  So the first ^C tries to exit the program
435     // cleanly, and the second one just kills it.
436     if (interrupted) {
437         stg_exit(EXIT_INTERRUPTED);
438     } else {
439         interruptStgRts();
440     }
441 }
442
443 /* -----------------------------------------------------------------------------
444  * Install default signal handlers.
445  *
446  * The RTS installs a default signal handler for catching
447  * SIGINT, so that we can perform an orderly shutdown.
448  *
449  * Haskell code may install their own SIGINT handler, which is
450  * fine, provided they're so kind as to put back the old one
451  * when they de-install.
452  *
453  * In addition to handling SIGINT, the RTS also handles SIGFPE
454  * by ignoring it.  Apparently IEEE requires floating-point
455  * exceptions to be ignored by default, but alpha-dec-osf3
456  * doesn't seem to do so.
457  * -------------------------------------------------------------------------- */
458 void
459 initDefaultHandlers()
460 {
461     struct sigaction action,oact;
462
463 #ifdef SMP
464     startup_guy = pthread_self();
465 #endif
466
467     // install the SIGINT handler
468     action.sa_handler = shutdown_handler;
469     sigemptyset(&action.sa_mask);
470     action.sa_flags = 0;
471     if (sigaction(SIGINT, &action, &oact) != 0) {
472         errorBelch("warning: failed to install SIGINT handler");
473     }
474
475 #if defined(HAVE_SIGINTERRUPT)
476     siginterrupt(SIGINT, 1);    // isn't this the default? --SDM
477 #endif
478
479     // install the SIGCONT handler
480     action.sa_handler = cont_handler;
481     sigemptyset(&action.sa_mask);
482     action.sa_flags = 0;
483     if (sigaction(SIGCONT, &action, &oact) != 0) {
484         errorBelch("warning: failed to install SIGCONT handler");
485     }
486
487     // install the SIGFPE handler
488
489     // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
490     // Apparently IEEE requires floating-point exceptions to be ignored by
491     // default, but alpha-dec-osf3 doesn't seem to do so.
492
493     // Commented out by SDM 2/7/2002: this causes an infinite loop on
494     // some architectures when an integer division by zero occurs: we
495     // don't recover from the floating point exception, and the
496     // program just generates another one immediately.
497 #if 0
498     action.sa_handler = SIG_IGN;
499     sigemptyset(&action.sa_mask);
500     action.sa_flags = 0;
501     if (sigaction(SIGFPE, &action, &oact) != 0) {
502         errorBelch("warning: failed to install SIGFPE handler");
503     }
504 #endif
505
506 #ifdef alpha_HOST_ARCH
507     ieee_set_fp_control(0);
508 #endif
509 }
510
511 #endif /* RTS_USER_SIGNALS */