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