RTS tidyup sweep, first phase
[ghc-hetmet.git] / rts / posix / Signals.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2005
4  *
5  * Signal processing / handling.
6  *
7  * ---------------------------------------------------------------------------*/
8
9 #include "PosixSource.h" 
10 #include "Rts.h"
11
12 #include "Schedule.h"
13 #include "RtsSignals.h"
14 #include "Signals.h"
15 #include "RtsUtils.h"
16 #include "Prelude.h"
17 #include "Stable.h"
18
19 #ifdef alpha_HOST_ARCH
20 # if defined(linux_HOST_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 #ifdef HAVE_ERRNO_H
36 # include <errno.h>
37 #endif
38
39 #include <stdlib.h>
40 #include <string.h>
41
42 /* This curious flag is provided for the benefit of the Haskell binding
43  * to POSIX.1 to control whether or not to include SA_NOCLDSTOP when
44  * installing a SIGCHLD handler. 
45  */
46 HsInt nocldstop = 0;
47
48 /* -----------------------------------------------------------------------------
49  * The table of signal handlers
50  * -------------------------------------------------------------------------- */
51
52 #if defined(RTS_USER_SIGNALS)
53
54 /* SUP: The type of handlers is a little bit, well, doubtful... */
55 StgInt *signal_handlers = NULL; /* Dynamically grown array of signal handlers */
56 static StgInt nHandlers = 0;    /* Size of handlers array */
57
58 static nat n_haskell_handlers = 0;
59
60 /* -----------------------------------------------------------------------------
61  * Allocate/resize the table of signal handlers.
62  * -------------------------------------------------------------------------- */
63
64 static void
65 more_handlers(int sig)
66 {
67     StgInt i;
68
69     if (sig < nHandlers)
70         return;
71
72     if (signal_handlers == NULL)
73         signal_handlers = (StgInt *)stgMallocBytes((sig + 1) * sizeof(StgInt), "more_handlers");
74     else
75         signal_handlers = (StgInt *)stgReallocBytes(signal_handlers, (sig + 1) * sizeof(StgInt), "more_handlers");
76
77     for(i = nHandlers; i <= sig; i++)
78         // Fill in the new slots with default actions
79         signal_handlers[i] = STG_SIG_DFL;
80
81     nHandlers = sig + 1;
82 }
83
84 // Here's the pipe into which we will send our signals
85 static int io_manager_pipe = -1;
86
87 #define IO_MANAGER_WAKEUP 0xff
88 #define IO_MANAGER_DIE    0xfe
89
90 void
91 setIOManagerPipe (int fd)
92 {
93     // only called when THREADED_RTS, but unconditionally
94     // compiled here because GHC.Conc depends on it.
95     if (io_manager_pipe < 0) {
96         io_manager_pipe = fd;
97     }
98 }
99
100 #if defined(THREADED_RTS)
101 void
102 ioManagerWakeup (void)
103 {
104     int r;
105     // Wake up the IO Manager thread by sending a byte down its pipe
106     if (io_manager_pipe >= 0) {
107         StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
108         r = write(io_manager_pipe, &byte, 1);
109         if (r == -1) { sysErrorBelch("ioManagerWakeup: write"); }
110     }
111 }
112
113 void
114 ioManagerDie (void)
115 {
116     int r;
117     // Ask the IO Manager thread to exit
118     if (io_manager_pipe >= 0) {
119         StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
120         r = write(io_manager_pipe, &byte, 1);
121         if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
122         close(io_manager_pipe);
123         io_manager_pipe = -1;
124     }
125 }
126
127 void
128 ioManagerStart (void)
129 {
130     // Make sure the IO manager thread is running
131     Capability *cap;
132     if (io_manager_pipe < 0) {
133         cap = rts_lock();
134         cap = rts_evalIO(cap,&base_GHCziConc_ensureIOManagerIsRunning_closure,NULL);
135         rts_unlock(cap);
136     }
137 }
138 #endif
139
140 #if !defined(THREADED_RTS)
141
142 #define N_PENDING_HANDLERS 16
143
144 siginfo_t pending_handler_buf[N_PENDING_HANDLERS];
145 siginfo_t *next_pending_handler = pending_handler_buf;
146
147 #endif /* THREADED_RTS */
148
149 /* -----------------------------------------------------------------------------
150  * Low-level signal handler
151  *
152  * Places the requested handler on a stack of pending handlers to be
153  * started up at the next context switch.
154  * -------------------------------------------------------------------------- */
155
156 static void
157 generic_handler(int sig USED_IF_THREADS,
158                 siginfo_t *info,
159                 void *p STG_UNUSED)
160 {
161 #if defined(THREADED_RTS)
162
163     if (io_manager_pipe != -1)
164     {
165         StgWord8 buf[sizeof(siginfo_t) + 1];
166         int r;
167
168         buf[0] = sig;
169         memcpy(buf+1, info, sizeof(siginfo_t));
170         r = write(io_manager_pipe, buf, sizeof(siginfo_t)+1);
171         if (r == -1 && errno == EAGAIN)
172         {
173             errorBelch("lost signal due to full pipe: %d\n", sig);
174         }
175     }
176     // If the IO manager hasn't told us what the FD of the write end
177     // of its pipe is, there's not much we can do here, so just ignore
178     // the signal..
179
180 #else /* not THREADED_RTS */
181
182     /* Can't call allocate from here.  Probably can't call malloc
183        either.  However, we have to schedule a new thread somehow.
184
185        It's probably ok to request a context switch and allow the
186        scheduler to  start the handler thread, but how do we
187        communicate this to the scheduler?
188
189        We need some kind of locking, but with low overhead (i.e. no
190        blocking signals every time around the scheduler).
191        
192        Signal Handlers are atomic (i.e. they can't be interrupted), and
193        we can make use of this.  We just need to make sure the
194        critical section of the scheduler can't be interrupted - the
195        only way to do this is to block signals.  However, we can lower
196        the overhead by only blocking signals when there are any
197        handlers to run, i.e. the set of pending handlers is
198        non-empty.
199     */
200        
201     /* We use a stack to store the pending signals.  We can't
202        dynamically grow this since we can't allocate any memory from
203        within a signal handler.
204
205        Hence unfortunately we have to bomb out if the buffer
206        overflows.  It might be acceptable to carry on in certain
207        circumstances, depending on the signal.  
208     */
209
210     memcpy(next_pending_handler, info, sizeof(siginfo_t));
211
212     next_pending_handler++;
213
214     // stack full?
215     if (next_pending_handler == &pending_handler_buf[N_PENDING_HANDLERS]) {
216         errorBelch("too many pending signals");
217         stg_exit(EXIT_FAILURE);
218     }
219     
220     contextSwitchCapability(&MainCapability);
221
222 #endif /* THREADED_RTS */
223 }
224
225 /* -----------------------------------------------------------------------------
226  * Blocking/Unblocking of the user signals
227  * -------------------------------------------------------------------------- */
228
229 static sigset_t userSignals;
230 static sigset_t savedSignals;
231
232 void
233 initUserSignals(void)
234 {
235     sigemptyset(&userSignals);
236 #ifndef THREADED_RTS
237     getStablePtr((StgPtr)&base_GHCziConc_runHandlers_closure); 
238     // needed to keep runHandler alive
239 #endif
240 }
241
242 void
243 blockUserSignals(void)
244 {
245     sigprocmask(SIG_BLOCK, &userSignals, &savedSignals);
246 }
247
248 void
249 unblockUserSignals(void)
250 {
251     sigprocmask(SIG_SETMASK, &savedSignals, NULL);
252 }
253
254 rtsBool
255 anyUserHandlers(void)
256 {
257     return n_haskell_handlers != 0;
258 }
259
260 #if !defined(THREADED_RTS)
261 void
262 awaitUserSignals(void)
263 {
264     while (!signals_pending() && sched_state == SCHED_RUNNING) {
265         pause();
266     }
267 }
268 #endif
269
270 /* -----------------------------------------------------------------------------
271  * Install a Haskell signal handler.
272  *
273  * We should really do this in Haskell in GHC.Conc, and share the
274  * signal_handlers array with the one there.
275  *
276  * -------------------------------------------------------------------------- */
277
278 int
279 stg_sig_install(int sig, int spi, void *mask)
280 {
281     sigset_t signals, osignals;
282     struct sigaction action;
283     StgInt previous_spi;
284
285     // Block the signal until we figure out what to do
286     // Count on this to fail if the signal number is invalid
287     if (sig < 0 || sigemptyset(&signals) ||
288         sigaddset(&signals, sig) || sigprocmask(SIG_BLOCK, &signals, &osignals)) {
289         return STG_SIG_ERR;
290     }
291     
292     more_handlers(sig);
293
294     previous_spi = signal_handlers[sig];
295
296     action.sa_flags = 0;
297     
298     switch(spi) {
299     case STG_SIG_IGN:
300         action.sa_handler = SIG_IGN;
301         break;
302
303     case STG_SIG_DFL:
304         action.sa_handler = SIG_DFL;
305         break;
306
307     case STG_SIG_RST:
308         action.sa_flags |= SA_RESETHAND;
309         /* fall through */
310     case STG_SIG_HAN:
311         action.sa_sigaction = generic_handler;
312         action.sa_flags |= SA_SIGINFO;
313         break;
314
315     default:
316         barf("stg_sig_install: bad spi");
317     }
318
319     if (mask != NULL)
320         action.sa_mask = *(sigset_t *)mask;
321     else
322         sigemptyset(&action.sa_mask);
323
324     action.sa_flags |= sig == SIGCHLD && nocldstop ? SA_NOCLDSTOP : 0;
325
326     if (sigaction(sig, &action, NULL))
327     {
328         errorBelch("sigaction");
329         return STG_SIG_ERR;
330     }
331
332     signal_handlers[sig] = spi;
333
334     switch(spi) {
335     case STG_SIG_RST:
336     case STG_SIG_HAN:
337         sigaddset(&userSignals, sig);
338         if (previous_spi != STG_SIG_HAN && previous_spi != STG_SIG_RST) {
339             n_haskell_handlers++;
340         }
341         break;
342
343     default:
344         sigdelset(&userSignals, sig);
345         if (previous_spi == STG_SIG_HAN || previous_spi == STG_SIG_RST) {
346             n_haskell_handlers--;
347         }
348         break;
349     }
350
351     if (sigprocmask(SIG_SETMASK, &osignals, NULL))
352     {
353         errorBelch("sigprocmask");
354         return STG_SIG_ERR;
355     }
356
357     return previous_spi;
358 }
359
360 /* -----------------------------------------------------------------------------
361  * Creating new threads for signal handlers.
362  * -------------------------------------------------------------------------- */
363
364 #if !defined(THREADED_RTS)
365 void
366 startSignalHandlers(Capability *cap)
367 {
368   siginfo_t *info;
369   int sig;
370
371   blockUserSignals();
372   
373   while (next_pending_handler != pending_handler_buf) {
374
375     next_pending_handler--;
376
377     sig = next_pending_handler->si_signo;
378     if (signal_handlers[sig] == STG_SIG_DFL) {
379         continue; // handler has been changed.
380     }
381
382     info = stgMallocBytes(sizeof(siginfo_t), "startSignalHandlers"); 
383            // freed by runHandler
384     memcpy(info, next_pending_handler, sizeof(siginfo_t));
385
386     scheduleThread (cap,
387         createIOThread(cap,
388                        RtsFlags.GcFlags.initialStkSize, 
389                        rts_apply(cap,
390                                  rts_apply(cap,
391                                            &base_GHCziConc_runHandlers_closure,
392                                            rts_mkPtr(cap, info)),
393                                  rts_mkInt(cap, info->si_signo))));
394   }
395
396   unblockUserSignals();
397 }
398 #endif
399
400 /* ----------------------------------------------------------------------------
401  * Mark signal handlers during GC.
402  * -------------------------------------------------------------------------- */
403
404 void
405 markSignalHandlers (evac_fn evac STG_UNUSED, void *user STG_UNUSED)
406 {
407     // nothing to do
408 }
409
410 #else /* !RTS_USER_SIGNALS */
411 StgInt 
412 stg_sig_install(StgInt sig STG_UNUSED,
413                 StgInt spi STG_UNUSED,
414                 void* mask STG_UNUSED)
415 {
416   //barf("User signals not supported");
417   return STG_SIG_DFL;
418 }
419
420 #endif
421
422 #if defined(RTS_USER_SIGNALS)
423 /* -----------------------------------------------------------------------------
424  * SIGINT handler.
425  *
426  * We like to shutdown nicely after receiving a SIGINT, write out the
427  * stats, write profiling info, close open files and flush buffers etc.
428  * -------------------------------------------------------------------------- */
429 static void
430 shutdown_handler(int sig STG_UNUSED)
431 {
432     // If we're already trying to interrupt the RTS, terminate with
433     // extreme prejudice.  So the first ^C tries to exit the program
434     // cleanly, and the second one just kills it.
435     if (sched_state >= SCHED_INTERRUPTING) {
436         stg_exit(EXIT_INTERRUPTED);
437     } else {
438         interruptStgRts();
439     }
440 }
441
442 /* -----------------------------------------------------------------------------
443  * Install default signal handlers.
444  *
445  * The RTS installs a default signal handler for catching
446  * SIGINT, so that we can perform an orderly shutdown.
447  *
448  * Haskell code may install their own SIGINT handler, which is
449  * fine, provided they're so kind as to put back the old one
450  * when they de-install.
451  *
452  * In addition to handling SIGINT, the RTS also handles SIGFPE
453  * by ignoring it.  Apparently IEEE requires floating-point
454  * exceptions to be ignored by default, but alpha-dec-osf3
455  * doesn't seem to do so.
456  * -------------------------------------------------------------------------- */
457 void
458 initDefaultHandlers(void)
459 {
460     struct sigaction action,oact;
461
462     // install the SIGINT handler
463     action.sa_handler = shutdown_handler;
464     sigemptyset(&action.sa_mask);
465     action.sa_flags = 0;
466     if (sigaction(SIGINT, &action, &oact) != 0) {
467         sysErrorBelch("warning: failed to install SIGINT handler");
468     }
469
470 #if defined(HAVE_SIGINTERRUPT)
471     siginterrupt(SIGINT, 1);    // isn't this the default? --SDM
472 #endif
473
474     // install the SIGFPE handler
475
476     // In addition to handling SIGINT, also handle SIGFPE by ignoring it.
477     // Apparently IEEE requires floating-point exceptions to be ignored by
478     // default, but alpha-dec-osf3 doesn't seem to do so.
479
480     // Commented out by SDM 2/7/2002: this causes an infinite loop on
481     // some architectures when an integer division by zero occurs: we
482     // don't recover from the floating point exception, and the
483     // program just generates another one immediately.
484 #if 0
485     action.sa_handler = SIG_IGN;
486     sigemptyset(&action.sa_mask);
487     action.sa_flags = 0;
488     if (sigaction(SIGFPE, &action, &oact) != 0) {
489         sysErrorBelch("warning: failed to install SIGFPE handler");
490     }
491 #endif
492
493 #ifdef alpha_HOST_ARCH
494     ieee_set_fp_control(0);
495 #endif
496
497     // ignore SIGPIPE; see #1619
498     action.sa_handler = SIG_IGN;
499     sigemptyset(&action.sa_mask);
500     action.sa_flags = 0;
501     if (sigaction(SIGPIPE, &action, &oact) != 0) {
502         sysErrorBelch("warning: failed to install SIGPIPE handler");
503     }
504 }
505
506 void
507 resetDefaultHandlers(void)
508 {
509     struct sigaction action;
510
511     action.sa_handler = SIG_DFL;
512     sigemptyset(&action.sa_mask);
513     action.sa_flags = 0;
514
515     // restore SIGINT
516     if (sigaction(SIGINT, &action, NULL) != 0) {
517         sysErrorBelch("warning: failed to uninstall SIGINT handler");
518     }
519     // restore SIGPIPE
520     if (sigaction(SIGPIPE, &action, NULL) != 0) {
521         sysErrorBelch("warning: failed to uninstall SIGPIPE handler");
522     }
523 }
524
525 void
526 freeSignalHandlers(void) {
527     if (signal_handlers != NULL) {
528         stgFree(signal_handlers);
529     }
530 }
531
532 #endif /* RTS_USER_SIGNALS */