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