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