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