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