Ruby  1.9.3p392(2013-02-22revision39386)
signal.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  signal.c -
4 
5  $Author: usa $
6  created at: Tue Dec 20 10:13:44 JST 1994
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9  Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10  Copyright (C) 2000 Information-technology Promotion Agency, Japan
11 
12 **********************************************************************/
13 
14 #include "ruby/ruby.h"
15 #include "vm_core.h"
16 #include <signal.h>
17 #include <stdio.h>
18 #include <errno.h>
19 #include "ruby_atomic.h"
20 
21 #if !defined(_WIN32) && !defined(HAVE_GCC_ATOMIC_BUILTINS)
24 {
25  rb_atomic_t old = *ptr;
26  *ptr = val;
27  return old;
28 }
29 #endif
30 
31 #if defined(__BEOS__) || defined(__HAIKU__)
32 #undef SIGBUS
33 #endif
34 
35 #ifdef HAVE_PTHREAD_SIGMASK
36 #define USE_TRAP_MASK 1
37 #else
38 #define USE_TRAP_MASK 0
39 #endif
40 
41 #ifndef NSIG
42 # define NSIG (_SIGMAX + 1) /* For QNX */
43 #endif
44 
45 static const struct signals {
46  const char *signm;
47  int signo;
48 } siglist [] = {
49  {"EXIT", 0},
50 #ifdef SIGHUP
51  {"HUP", SIGHUP},
52 #endif
53  {"INT", SIGINT},
54 #ifdef SIGQUIT
55  {"QUIT", SIGQUIT},
56 #endif
57 #ifdef SIGILL
58  {"ILL", SIGILL},
59 #endif
60 #ifdef SIGTRAP
61  {"TRAP", SIGTRAP},
62 #endif
63 #ifdef SIGIOT
64  {"IOT", SIGIOT},
65 #endif
66 #ifdef SIGABRT
67  {"ABRT", SIGABRT},
68 #endif
69 #ifdef SIGEMT
70  {"EMT", SIGEMT},
71 #endif
72 #ifdef SIGFPE
73  {"FPE", SIGFPE},
74 #endif
75 #ifdef SIGKILL
76  {"KILL", SIGKILL},
77 #endif
78 #ifdef SIGBUS
79  {"BUS", SIGBUS},
80 #endif
81 #ifdef SIGSEGV
82  {"SEGV", SIGSEGV},
83 #endif
84 #ifdef SIGSYS
85  {"SYS", SIGSYS},
86 #endif
87 #ifdef SIGPIPE
88  {"PIPE", SIGPIPE},
89 #endif
90 #ifdef SIGALRM
91  {"ALRM", SIGALRM},
92 #endif
93 #ifdef SIGTERM
94  {"TERM", SIGTERM},
95 #endif
96 #ifdef SIGURG
97  {"URG", SIGURG},
98 #endif
99 #ifdef SIGSTOP
100  {"STOP", SIGSTOP},
101 #endif
102 #ifdef SIGTSTP
103  {"TSTP", SIGTSTP},
104 #endif
105 #ifdef SIGCONT
106  {"CONT", SIGCONT},
107 #endif
108 #ifdef SIGCHLD
109  {"CHLD", SIGCHLD},
110 #endif
111 #ifdef SIGCLD
112  {"CLD", SIGCLD},
113 #else
114 # ifdef SIGCHLD
115  {"CLD", SIGCHLD},
116 # endif
117 #endif
118 #ifdef SIGTTIN
119  {"TTIN", SIGTTIN},
120 #endif
121 #ifdef SIGTTOU
122  {"TTOU", SIGTTOU},
123 #endif
124 #ifdef SIGIO
125  {"IO", SIGIO},
126 #endif
127 #ifdef SIGXCPU
128  {"XCPU", SIGXCPU},
129 #endif
130 #ifdef SIGXFSZ
131  {"XFSZ", SIGXFSZ},
132 #endif
133 #ifdef SIGVTALRM
134  {"VTALRM", SIGVTALRM},
135 #endif
136 #ifdef SIGPROF
137  {"PROF", SIGPROF},
138 #endif
139 #ifdef SIGWINCH
140  {"WINCH", SIGWINCH},
141 #endif
142 #ifdef SIGUSR1
143  {"USR1", SIGUSR1},
144 #endif
145 #ifdef SIGUSR2
146  {"USR2", SIGUSR2},
147 #endif
148 #ifdef SIGLOST
149  {"LOST", SIGLOST},
150 #endif
151 #ifdef SIGMSG
152  {"MSG", SIGMSG},
153 #endif
154 #ifdef SIGPWR
155  {"PWR", SIGPWR},
156 #endif
157 #ifdef SIGPOLL
158  {"POLL", SIGPOLL},
159 #endif
160 #ifdef SIGDANGER
161  {"DANGER", SIGDANGER},
162 #endif
163 #ifdef SIGMIGRATE
164  {"MIGRATE", SIGMIGRATE},
165 #endif
166 #ifdef SIGPRE
167  {"PRE", SIGPRE},
168 #endif
169 #ifdef SIGGRANT
170  {"GRANT", SIGGRANT},
171 #endif
172 #ifdef SIGRETRACT
173  {"RETRACT", SIGRETRACT},
174 #endif
175 #ifdef SIGSOUND
176  {"SOUND", SIGSOUND},
177 #endif
178 #ifdef SIGINFO
179  {"INFO", SIGINFO},
180 #endif
181  {NULL, 0}
182 };
183 
184 static int
185 signm2signo(const char *nm)
186 {
187  const struct signals *sigs;
188 
189  for (sigs = siglist; sigs->signm; sigs++)
190  if (strcmp(sigs->signm, nm) == 0)
191  return sigs->signo;
192  return 0;
193 }
194 
195 static const char*
196 signo2signm(int no)
197 {
198  const struct signals *sigs;
199 
200  for (sigs = siglist; sigs->signm; sigs++)
201  if (sigs->signo == no)
202  return sigs->signm;
203  return 0;
204 }
205 
206 const char *
208 {
209  return signo2signm(no);
210 }
211 
212 /*
213  * call-seq:
214  * SignalException.new(sig_name) -> signal_exception
215  * SignalException.new(sig_number [, name]) -> signal_exception
216  *
217  * Construct a new SignalException object. +sig_name+ should be a known
218  * signal name.
219  */
220 
221 static VALUE
223 {
224  int argnum = 1;
225  VALUE sig = Qnil;
226  int signo;
227  const char *signm;
228 
229  if (argc > 0) {
230  sig = rb_check_to_integer(argv[0], "to_int");
231  if (!NIL_P(sig)) argnum = 2;
232  else sig = argv[0];
233  }
234  if (argc < 1 || argnum < argc) {
235  rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
236  argc, argnum);
237  }
238  if (argnum == 2) {
239  signo = NUM2INT(sig);
240  if (signo < 0 || signo > NSIG) {
241  rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
242  }
243  if (argc > 1) {
244  sig = argv[1];
245  }
246  else {
247  signm = signo2signm(signo);
248  if (signm) {
249  sig = rb_sprintf("SIG%s", signm);
250  }
251  else {
252  sig = rb_sprintf("SIG%u", signo);
253  }
254  }
255  }
256  else {
257  signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig);
258  if (strncmp(signm, "SIG", 3) == 0) signm += 3;
259  signo = signm2signo(signm);
260  if (!signo) {
261  rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
262  }
263  sig = rb_sprintf("SIG%s", signm);
264  }
265  rb_call_super(1, &sig);
266  rb_iv_set(self, "signo", INT2NUM(signo));
267 
268  return self;
269 }
270 
271 /*
272  * call-seq:
273  * signal_exception.signo -> num
274  *
275  * Returns a signal number.
276  */
277 
278 static VALUE
280 {
281  return rb_iv_get(self, "signo");
282 }
283 
284 /* :nodoc: */
285 static VALUE
287 {
288  VALUE args[2];
289 
290  args[0] = INT2FIX(SIGINT);
291  rb_scan_args(argc, argv, "01", &args[1]);
292  return rb_call_super(2, args);
293 }
294 
295 void
297 {
298  signal(sig, SIG_DFL);
299  raise(sig);
300 }
301 
302 /*
303  * call-seq:
304  * Process.kill(signal, pid, ...) -> fixnum
305  *
306  * Sends the given signal to the specified process id(s), or to the
307  * current process if _pid_ is zero. _signal_ may be an
308  * integer signal number or a POSIX signal name (either with or without
309  * a +SIG+ prefix). If _signal_ is negative (or starts
310  * with a minus sign), kills process groups instead of
311  * processes. Not all signals are available on all platforms.
312  *
313  * pid = fork do
314  * Signal.trap("HUP") { puts "Ouch!"; exit }
315  * # ... do some work ...
316  * end
317  * # ...
318  * Process.kill("HUP", pid)
319  * Process.wait
320  *
321  * <em>produces:</em>
322  *
323  * Ouch!
324  *
325  * If _signal_ is an integer but wrong for signal,
326  * <code>Errno::EINVAL</code> or +RangeError+ will be raised.
327  * Otherwise unless _signal_ is a +String+ or a +Symbol+, and a known
328  * signal name, +ArgumentError+ will be raised.
329  *
330  * Also, <code>Errno::ESRCH</code> or +RangeError+ for invalid _pid_,
331  * <code>Errno::EPERM</code> when failed because of no privilege,
332  * will be raised. In these cases, signals may have been sent to
333  * preceding processes.
334  */
335 
336 VALUE
338 {
339 #ifndef HAS_KILLPG
340 #define killpg(pg, sig) kill(-(pg), (sig))
341 #endif
342  int negative = 0;
343  int sig;
344  int i;
345  volatile VALUE str;
346  const char *s;
347 
348  rb_secure(2);
349  if (argc < 2)
350  rb_raise(rb_eArgError, "wrong number of arguments (%d for at least 2)", argc);
351  switch (TYPE(argv[0])) {
352  case T_FIXNUM:
353  sig = FIX2INT(argv[0]);
354  break;
355 
356  case T_SYMBOL:
357  s = rb_id2name(SYM2ID(argv[0]));
358  if (!s) rb_raise(rb_eArgError, "bad signal");
359  goto str_signal;
360 
361  case T_STRING:
362  s = RSTRING_PTR(argv[0]);
363  str_signal:
364  if (s[0] == '-') {
365  negative++;
366  s++;
367  }
368  if (strncmp("SIG", s, 3) == 0)
369  s += 3;
370  if((sig = signm2signo(s)) == 0)
371  rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
372 
373  if (negative)
374  sig = -sig;
375  break;
376 
377  default:
378  str = rb_check_string_type(argv[0]);
379  if (!NIL_P(str)) {
380  s = RSTRING_PTR(str);
381  goto str_signal;
382  }
383  rb_raise(rb_eArgError, "bad signal type %s",
384  rb_obj_classname(argv[0]));
385  break;
386  }
387 
388  if (sig < 0) {
389  sig = -sig;
390  for (i=1; i<argc; i++) {
391  if (killpg(NUM2PIDT(argv[i]), sig) < 0)
392  rb_sys_fail(0);
393  }
394  }
395  else {
396  for (i=1; i<argc; i++) {
397  if (kill(NUM2PIDT(argv[i]), sig) < 0)
398  rb_sys_fail(0);
399  }
400  }
402  return INT2FIX(i-1);
403 }
404 
405 static struct {
408 } signal_buff;
409 
410 #ifdef __dietlibc__
411 #define sighandler_t sh_t
412 #endif
413 
414 typedef RETSIGTYPE (*sighandler_t)(int);
415 #ifdef USE_SIGALTSTACK
416 typedef void ruby_sigaction_t(int, siginfo_t*, void*);
417 #define SIGINFO_ARG , siginfo_t *info, void *ctx
418 #else
419 typedef RETSIGTYPE ruby_sigaction_t(int);
420 #define SIGINFO_ARG
421 #endif
422 
423 #ifdef POSIX_SIGNAL
424 
425 #ifdef USE_SIGALTSTACK
426 /* alternate stack for SIGSEGV */
427 void
428 rb_register_sigaltstack(rb_thread_t *th)
429 {
430  stack_t newSS, oldSS;
431 
432  if (!th->altstack)
433  rb_bug("rb_register_sigaltstack: th->altstack not initialized\n");
434 
435  newSS.ss_sp = th->altstack;
436  newSS.ss_size = ALT_STACK_SIZE;
437  newSS.ss_flags = 0;
438 
439  sigaltstack(&newSS, &oldSS); /* ignore error. */
440 }
441 #endif /* USE_SIGALTSTACK */
442 
443 static sighandler_t
444 ruby_signal(int signum, sighandler_t handler)
445 {
446  struct sigaction sigact, old;
447 
448 #if 0
449  rb_trap_accept_nativethreads[signum] = 0;
450 #endif
451 
452  sigemptyset(&sigact.sa_mask);
453 #ifdef USE_SIGALTSTACK
454  sigact.sa_sigaction = (ruby_sigaction_t*)handler;
455  sigact.sa_flags = SA_SIGINFO;
456 #else
457  sigact.sa_handler = handler;
458  sigact.sa_flags = 0;
459 #endif
460 
461 #ifdef SA_NOCLDWAIT
462  if (signum == SIGCHLD && handler == SIG_IGN)
463  sigact.sa_flags |= SA_NOCLDWAIT;
464 #endif
465 #if defined(SA_ONSTACK) && defined(USE_SIGALTSTACK)
466  if (signum == SIGSEGV || signum == SIGBUS)
467  sigact.sa_flags |= SA_ONSTACK;
468 #endif
469  if (sigaction(signum, &sigact, &old) < 0) {
470  if (errno != 0 && errno != EINVAL) {
471  rb_bug_errno("sigaction", errno);
472  }
473  }
474  return old.sa_handler;
475 }
476 
478 posix_signal(int signum, sighandler_t handler)
479 {
480  return ruby_signal(signum, handler);
481 }
482 
483 #else /* !POSIX_SIGNAL */
484 #define ruby_signal(sig,handler) (/* rb_trap_accept_nativethreads[(sig)] = 0,*/ signal((sig),(handler)))
485 #if 0 /* def HAVE_NATIVETHREAD */
486 static sighandler_t
487 ruby_nativethread_signal(int signum, sighandler_t handler)
488 {
489  sighandler_t old;
490 
491  old = signal(signum, handler);
492  rb_trap_accept_nativethreads[signum] = 1;
493  return old;
494 }
495 #endif
496 #endif
497 
498 static RETSIGTYPE
499 sighandler(int sig)
500 {
501  ATOMIC_INC(signal_buff.cnt[sig]);
502  ATOMIC_INC(signal_buff.size);
504 #if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
505  ruby_signal(sig, sighandler);
506 #endif
507 }
508 
509 int
511 {
512  return signal_buff.size;
513 }
514 
515 #if USE_TRAP_MASK
516 static sigset_t trap_last_mask;
517 #endif
518 
519 #if HAVE_PTHREAD_H
520 #include <pthread.h>
521 #endif
522 
523 void
525 {
526 #if USE_TRAP_MASK
527  sigset_t mask;
528  sigfillset(&mask);
529  sigdelset(&mask, SIGVTALRM);
530  sigdelset(&mask, SIGSEGV);
531  pthread_sigmask(SIG_SETMASK, &mask, NULL);
532 #endif
533 }
534 
535 void
537 {
538 #if USE_TRAP_MASK
539  sigset_t mask;
540  sigemptyset(&mask);
541  pthread_sigmask(SIG_SETMASK, &mask, NULL);
542 #endif
543 }
544 
545 int
547 {
548  int i, sig = 0;
549 
550  if (signal_buff.size != 0) {
551  for (i=1; i<RUBY_NSIG; i++) {
552  if (signal_buff.cnt[i] > 0) {
554  {
555  ATOMIC_DEC(signal_buff.cnt[i]);
556  ATOMIC_DEC(signal_buff.size);
557  }
559  sig = i;
560  break;
561  }
562  }
563  }
564  return sig;
565 }
566 
567 #ifdef SIGBUS
568 static RETSIGTYPE
569 sigbus(int sig SIGINFO_ARG)
570 {
571 /*
572  * Mac OS X makes KERN_PROTECTION_FAILURE when thread touch guard page.
573  * and it's delivered as SIGBUS instaed of SIGSEGV to userland. It's crazy
574  * wrong IMHO. but anyway we have to care it. Sigh.
575  */
576 #if defined __MACH__ && defined __APPLE__ && defined USE_SIGALTSTACK
577  int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
579  rb_thread_t *th = GET_THREAD();
580  if (ruby_stack_overflowed_p(th, info->si_addr)) {
582  }
583 #endif
584  rb_bug("Bus Error");
585 }
586 #endif
587 
588 #ifdef SIGSEGV
589 static int segv_received = 0;
590 static RETSIGTYPE
591 sigsegv(int sig SIGINFO_ARG)
592 {
593 #ifdef USE_SIGALTSTACK
594  int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
596  rb_thread_t *th = GET_THREAD();
597  if (ruby_stack_overflowed_p(th, info->si_addr)) {
599  }
600 #endif
601  if (segv_received) {
602  fprintf(stderr, "SEGV received in SEGV handler\n");
603  abort();
604  }
605  else {
606  extern int ruby_disable_gc_stress;
607  segv_received = 1;
608  ruby_disable_gc_stress = 1;
609  rb_bug("Segmentation fault");
610  }
611 }
612 #endif
613 
614 static void
615 signal_exec(VALUE cmd, int safe, int sig)
616 {
617  VALUE signum = INT2NUM(sig);
618  rb_eval_cmd(cmd, rb_ary_new3(1, signum), safe);
619 }
620 
621 void
623 {
624  rb_vm_t *vm = GET_VM();
625  VALUE trap_exit = vm->trap_list[0].cmd;
626 
627  if (trap_exit) {
628  vm->trap_list[0].cmd = 0;
629  signal_exec(trap_exit, vm->trap_list[0].safe, 0);
630  }
631 }
632 
633 void
635 {
636  rb_vm_t *vm = GET_VM();
637  VALUE cmd = vm->trap_list[sig].cmd;
638  int safe = vm->trap_list[sig].safe;
639 
640  if (cmd == 0) {
641  switch (sig) {
642  case SIGINT:
643  rb_interrupt();
644  break;
645 #ifdef SIGHUP
646  case SIGHUP:
647 #endif
648 #ifdef SIGQUIT
649  case SIGQUIT:
650 #endif
651 #ifdef SIGTERM
652  case SIGTERM:
653 #endif
654 #ifdef SIGALRM
655  case SIGALRM:
656 #endif
657 #ifdef SIGUSR1
658  case SIGUSR1:
659 #endif
660 #ifdef SIGUSR2
661  case SIGUSR2:
662 #endif
663  rb_threadptr_signal_raise(th, sig);
664  break;
665  }
666  }
667  else if (cmd == Qundef) {
669  }
670  else {
671  signal_exec(cmd, safe, sig);
672  }
673 }
674 
675 struct trap_arg {
676 #if USE_TRAP_MASK
677  sigset_t mask;
678 #endif
679  int sig;
682 };
683 
684 static sighandler_t
686 {
688  switch (sig) {
689  case SIGINT:
690 #ifdef SIGHUP
691  case SIGHUP:
692 #endif
693 #ifdef SIGQUIT
694  case SIGQUIT:
695 #endif
696 #ifdef SIGTERM
697  case SIGTERM:
698 #endif
699 #ifdef SIGALRM
700  case SIGALRM:
701 #endif
702 #ifdef SIGUSR1
703  case SIGUSR1:
704 #endif
705 #ifdef SIGUSR2
706  case SIGUSR2:
707 #endif
708  func = sighandler;
709  break;
710 #ifdef SIGBUS
711  case SIGBUS:
712  func = (sighandler_t)sigbus;
713  break;
714 #endif
715 #ifdef SIGSEGV
716  case SIGSEGV:
717  func = (sighandler_t)sigsegv;
718 # ifdef USE_SIGALTSTACK
719  rb_register_sigaltstack(GET_THREAD());
720 # endif
721  break;
722 #endif
723 #ifdef SIGPIPE
724  case SIGPIPE:
725  func = SIG_IGN;
726  break;
727 #endif
728  default:
729  func = SIG_DFL;
730  break;
731  }
732 
733  return func;
734 }
735 
736 static sighandler_t
737 trap_handler(VALUE *cmd, int sig)
738 {
740  VALUE command;
741 
742  if (NIL_P(*cmd)) {
743  func = SIG_IGN;
744  }
745  else {
746  command = rb_check_string_type(*cmd);
747  if (NIL_P(command) && SYMBOL_P(*cmd)) {
748  command = rb_id2str(SYM2ID(*cmd));
749  if (!command) rb_raise(rb_eArgError, "bad handler");
750  }
751  if (!NIL_P(command)) {
752  SafeStringValue(command); /* taint check */
753  *cmd = command;
754  switch (RSTRING_LEN(command)) {
755  case 0:
756  goto sig_ign;
757  break;
758  case 14:
759  if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) {
760  func = SIG_DFL;
761  *cmd = 0;
762  }
763  break;
764  case 7:
765  if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) {
766 sig_ign:
767  func = SIG_IGN;
768  *cmd = 0;
769  }
770  else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
771 sig_dfl:
772  func = default_handler(sig);
773  *cmd = 0;
774  }
775  else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) {
776  goto sig_dfl;
777  }
778  break;
779  case 6:
780  if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) {
781  goto sig_ign;
782  }
783  break;
784  case 4:
785  if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) {
786  *cmd = Qundef;
787  }
788  break;
789  }
790  }
791  else {
792  rb_proc_t *proc;
793  GetProcPtr(*cmd, proc);
794  }
795  }
796 
797  return func;
798 }
799 
800 static int
802 {
803  int sig = -1;
804  const char *s;
805 
806  switch (TYPE(vsig)) {
807  case T_FIXNUM:
808  sig = FIX2INT(vsig);
809  if (sig < 0 || sig >= NSIG) {
810  rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
811  }
812  break;
813 
814  case T_SYMBOL:
815  s = rb_id2name(SYM2ID(vsig));
816  if (!s) rb_raise(rb_eArgError, "bad signal");
817  goto str_signal;
818 
819  default:
820  s = StringValuePtr(vsig);
821 
822  str_signal:
823  if (strncmp("SIG", s, 3) == 0)
824  s += 3;
825  sig = signm2signo(s);
826  if (sig == 0 && strcmp(s, "EXIT") != 0)
827  rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
828  }
829  return sig;
830 }
831 
832 static VALUE
833 trap(struct trap_arg *arg)
834 {
835  sighandler_t oldfunc, func = arg->func;
836  VALUE oldcmd, command = arg->cmd;
837  int sig = arg->sig;
838  rb_vm_t *vm = GET_VM();
839 
840  oldfunc = ruby_signal(sig, func);
841  oldcmd = vm->trap_list[sig].cmd;
842  switch (oldcmd) {
843  case 0:
844  if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
845  else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
846  else oldcmd = Qnil;
847  break;
848  case Qundef:
849  oldcmd = rb_str_new2("EXIT");
850  break;
851  }
852 
853  vm->trap_list[sig].cmd = command;
854  vm->trap_list[sig].safe = rb_safe_level();
855  /* enable at least specified signal. */
856 #if USE_TRAP_MASK
857  sigdelset(&arg->mask, sig);
858 #endif
859  return oldcmd;
860 }
861 
862 #if USE_TRAP_MASK
863 static VALUE
864 trap_ensure(struct trap_arg *arg)
865 {
866  /* enable interrupt */
867  pthread_sigmask(SIG_SETMASK, &arg->mask, NULL);
868  trap_last_mask = arg->mask;
869  return 0;
870 }
871 #endif
872 
873 void
875 {
876 #if USE_TRAP_MASK
877  pthread_sigmask(SIG_SETMASK, &trap_last_mask, NULL);
878 #endif
879 }
880 
881 /*
882  * call-seq:
883  * Signal.trap( signal, command ) -> obj
884  * Signal.trap( signal ) {| | block } -> obj
885  *
886  * Specifies the handling of signals. The first parameter is a signal
887  * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
888  * signal number. The characters ``SIG'' may be omitted from the
889  * signal name. The command or block specifies code to be run when the
890  * signal is raised.
891  * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
892  * will be ignored.
893  * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
894  * will be invoked.
895  * If the command is ``EXIT'', the script will be terminated by the signal.
896  * If the command is ``SYSTEM_DEFAULT'', the operating system's default
897  * handler will be invoked.
898  * Otherwise, the given command or block will be run.
899  * The special signal name ``EXIT'' or signal number zero will be
900  * invoked just prior to program termination.
901  * trap returns the previous handler for the given signal.
902  *
903  * Signal.trap(0, proc { puts "Terminating: #{$$}" })
904  * Signal.trap("CLD") { puts "Child died" }
905  * fork && Process.wait
906  *
907  * produces:
908  * Terminating: 27461
909  * Child died
910  * Terminating: 27460
911  */
912 static VALUE
914 {
915  struct trap_arg arg;
916 
917  rb_secure(2);
918  if (argc < 1 || argc > 2) {
919  rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
920  }
921 
922  arg.sig = trap_signm(argv[0]);
923  if (argc == 1) {
924  arg.cmd = rb_block_proc();
925  arg.func = sighandler;
926  }
927  else {
928  arg.cmd = argv[1];
929  arg.func = trap_handler(&arg.cmd, arg.sig);
930  }
931 
932  if (OBJ_TAINTED(arg.cmd)) {
933  rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
934  }
935 #if USE_TRAP_MASK
936  {
937  sigset_t fullmask;
938 
939  /* disable interrupt */
940  sigfillset(&fullmask);
941  pthread_sigmask(SIG_BLOCK, &fullmask, &arg.mask);
942 
943  return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg);
944  }
945 #else
946  return trap(&arg);
947 #endif
948 }
949 
950 /*
951  * call-seq:
952  * Signal.list -> a_hash
953  *
954  * Returns a list of signal names mapped to the corresponding
955  * underlying signal numbers.
956  *
957  * Signal.list #=> {"EXIT"=>0, "HUP"=>1, "INT"=>2, "QUIT"=>3, "ILL"=>4, "TRAP"=>5, "IOT"=>6, "ABRT"=>6, "FPE"=>8, "KILL"=>9, "BUS"=>7, "SEGV"=>11, "SYS"=>31, "PIPE"=>13, "ALRM"=>14, "TERM"=>15, "URG"=>23, "STOP"=>19, "TSTP"=>20, "CONT"=>18, "CHLD"=>17, "CLD"=>17, "TTIN"=>21, "TTOU"=>22, "IO"=>29, "XCPU"=>24, "XFSZ"=>25, "VTALRM"=>26, "PROF"=>27, "WINCH"=>28, "USR1"=>10, "USR2"=>12, "PWR"=>30, "POLL"=>29}
958  */
959 static VALUE
960 sig_list(void)
961 {
962  VALUE h = rb_hash_new();
963  const struct signals *sigs;
964 
965  for (sigs = siglist; sigs->signm; sigs++) {
966  rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
967  }
968  return h;
969 }
970 
971 static void
972 install_sighandler(int signum, sighandler_t handler)
973 {
974  sighandler_t old;
975 
976  old = ruby_signal(signum, handler);
977  if (old != SIG_DFL) {
978  ruby_signal(signum, old);
979  }
980 }
981 
982 #if defined(SIGCLD) || defined(SIGCHLD)
983 static void
984 init_sigchld(int sig)
985 {
986  sighandler_t oldfunc;
987 #if USE_TRAP_MASK
988  sigset_t mask;
989  sigset_t fullmask;
990 
991  /* disable interrupt */
992  sigfillset(&fullmask);
993  pthread_sigmask(SIG_BLOCK, &fullmask, &mask);
994 #endif
995 
996  oldfunc = ruby_signal(sig, SIG_DFL);
997  if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
998  ruby_signal(sig, oldfunc);
999  } else {
1000  GET_VM()->trap_list[sig].cmd = 0;
1001  }
1002 
1003 #if USE_TRAP_MASK
1004  sigdelset(&mask, sig);
1005  pthread_sigmask(SIG_SETMASK, &mask, NULL);
1006  trap_last_mask = mask;
1007 #endif
1008 }
1009 #endif
1010 
1011 void
1013 {
1014  sighandler_t oldfunc;
1015 
1016  oldfunc = ruby_signal(SIGINT, SIG_IGN);
1017  if (oldfunc == sighandler) {
1018  ruby_signal(SIGINT, SIG_DFL);
1019  }
1020 }
1021 
1022 
1024 #ifndef RUBY_DEBUG_ENV
1025 #define ruby_enable_coredump 0
1026 #endif
1027 
1028 /*
1029  * Many operating systems allow signals to be sent to running
1030  * processes. Some signals have a defined effect on the process, while
1031  * others may be trapped at the code level and acted upon. For
1032  * example, your process may trap the USR1 signal and use it to toggle
1033  * debugging, and may use TERM to initiate a controlled shutdown.
1034  *
1035  * pid = fork do
1036  * Signal.trap("USR1") do
1037  * $debug = !$debug
1038  * puts "Debug now: #$debug"
1039  * end
1040  * Signal.trap("TERM") do
1041  * puts "Terminating..."
1042  * shutdown()
1043  * end
1044  * # . . . do some work . . .
1045  * end
1046  *
1047  * Process.detach(pid)
1048  *
1049  * # Controlling program:
1050  * Process.kill("USR1", pid)
1051  * # ...
1052  * Process.kill("USR1", pid)
1053  * # ...
1054  * Process.kill("TERM", pid)
1055  *
1056  * produces:
1057  * Debug now: true
1058  * Debug now: false
1059  * Terminating...
1060  *
1061  * The list of available signal names and their interpretation is
1062  * system dependent. Signal delivery semantics may also vary between
1063  * systems; in particular signal delivery may not always be reliable.
1064  */
1065 void
1067 {
1068  VALUE mSignal = rb_define_module("Signal");
1069 
1070  rb_define_global_function("trap", sig_trap, -1);
1071  rb_define_module_function(mSignal, "trap", sig_trap, -1);
1072  rb_define_module_function(mSignal, "list", sig_list, 0);
1073 
1074  rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
1076  rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
1077  rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
1078 
1080 #ifdef SIGHUP
1081  install_sighandler(SIGHUP, sighandler);
1082 #endif
1083 #ifdef SIGQUIT
1084  install_sighandler(SIGQUIT, sighandler);
1085 #endif
1086 #ifdef SIGTERM
1087  install_sighandler(SIGTERM, sighandler);
1088 #endif
1089 #ifdef SIGALRM
1090  install_sighandler(SIGALRM, sighandler);
1091 #endif
1092 #ifdef SIGUSR1
1093  install_sighandler(SIGUSR1, sighandler);
1094 #endif
1095 #ifdef SIGUSR2
1096  install_sighandler(SIGUSR2, sighandler);
1097 #endif
1098 
1099  if (!ruby_enable_coredump) {
1100 #ifdef SIGBUS
1101  install_sighandler(SIGBUS, (sighandler_t)sigbus);
1102 #endif
1103 #ifdef SIGSEGV
1104 # ifdef USE_SIGALTSTACK
1105  rb_register_sigaltstack(GET_THREAD());
1106 # endif
1107  install_sighandler(SIGSEGV, (sighandler_t)sigsegv);
1108 #endif
1109  }
1110 #ifdef SIGPIPE
1111  install_sighandler(SIGPIPE, SIG_IGN);
1112 #endif
1113 
1114 #if defined(SIGCLD)
1115  init_sigchld(SIGCLD);
1116 #elif defined(SIGCHLD)
1117  init_sigchld(SIGCHLD);
1118 #endif
1119 }
1120