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