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