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