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