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