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