Ruby 2.0.0p353(2013-11-22revision43784)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

signal.c
Go to the documentation of this file.
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
27 rb_atomic_t
28 ruby_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
35 rb_atomic_t
36 ruby_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
55 static 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
194 static int
195 signm2signo(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
205 static const char*
206 signo2signm(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 */
229 static VALUE
230 sig_signame(VALUE recv, VALUE signo)
231 {
232 const char *signame = signo2signm(NUM2INT(signo));
233 return rb_str_new_cstr(signame);
234 }
235
236 const char *
237 ruby_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
251 static VALUE
252 esignal_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
305 static VALUE
306 esignal_signo(VALUE self)
307 {
308 return rb_iv_get(self, "signo");
309 }
310
311 /* :nodoc: */
312 static VALUE
313 interrupt_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
322 void
323 ruby_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
363 VALUE
364 rb_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
431 static 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
440 typedef RETSIGTYPE (*sighandler_t)(int);
441 #ifdef USE_SIGALTSTACK
442 typedef void ruby_sigaction_t(int, siginfo_t*, void*);
443 #define SIGINFO_ARG , siginfo_t *info, void *ctx
444 #else
445 typedef RETSIGTYPE ruby_sigaction_t(int);
446 #define SIGINFO_ARG
447 #endif
448
449 #ifdef USE_SIGALTSTACK
450 int 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 */
472 void
473 rb_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
489 static sighandler_t
490 ruby_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
527 sighandler_t
528 posix_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 */
536 static sighandler_t
537 ruby_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
548 static RETSIGTYPE
549 sighandler(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
559 int
560 rb_signal_buff_size(void)
561 {
562 return signal_buff.size;
563 }
564
565 #if HAVE_PTHREAD_H
566 #include <pthread.h>
567 #endif
568
569 static void
570 rb_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
579 static void
580 rb_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
589 int
590 rb_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
609 static void
610 check_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
625 static RETSIGTYPE
626 sigbus(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
641 static 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
654 static int segv_received = 0;
655 extern int ruby_disable_gc_stress;
656
657 static RETSIGTYPE
658 sigsegv(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
676 static void
677 signal_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
699 void
700 rb_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
711 void
712 rb_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
753 static sighandler_t
754 default_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
802 static sighandler_t
803 trap_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) {
832 sig_ign:
833 func = SIG_IGN;
834 *cmd = 0;
835 }
836 else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
837 sig_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
867 static int
868 trap_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
899 static VALUE
900 trap(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
930 static int
931 reserved_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 */
991 static VALUE
992 sig_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 */
1035 static VALUE
1036 sig_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
1047 static void
1048 install_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)
1063 static void
1064 init_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
1079 void
1080 ruby_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
1091 int 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 */
1133 void
1134 Init_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 }
sig_list
static VALUE sig_list(void)
Definition: signal.c:1036
signal_exec
static void signal_exec(VALUE cmd, int safe, int sig)
Definition: signal.c:677
int
VP_EXPORT int
Definition: bigdecimal.c:5050
rb_interrupt
void rb_interrupt(void)
Definition: eval.c:545
ruby_thread_stack_overflow
void ruby_thread_stack_overflow(rb_thread_t *th)
Definition: thread.c:2031
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:290
th
static VALUE VALUE th
Definition: tcltklib.c:2948
trap
static VALUE trap(int sig, sighandler_t func, VALUE command)
Definition: signal.c:900
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:396
rb_vm_struct::cmd
VALUE cmd
Definition: vm_core.h:372
rb_id2str
VALUE rb_id2str(ID id)
Definition: ripper.c:16944
rb_iv_set
VALUE rb_iv_set(VALUE, const char *, VALUE)
Definition: variable.c:2591
rb_eSignal
VALUE rb_eSignal
Definition: error.c:507
rb_eval_cmd
VALUE rb_eval_cmd(VALUE, VALUE, int)
Definition: vm_eval.c:1447
UNLIMITED_ARGUMENTS
#define UNLIMITED_ARGUMENTS
signals::signm
const char * signm
Definition: signal.c:56
GetProcPtr
#define GetProcPtr(obj, ptr)
Definition: vm_core.h:665
ruby.h
NUM2PIDT
#define NUM2PIDT(v)
Definition: ruby.h:332
proc
VALUE proc
Definition: tcltklib.c:2959
SIGINFO_ARG
#define SIGINFO_ARG
Definition: signal.c:446
func
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:108
interrupt_init
static VALUE interrupt_init(int argc, VALUE *argv, VALUE self)
Definition: signal.c:313
rb_secure
void rb_secure(int)
Definition: safe.c:79
i
ssize_t i
Definition: bigdecimal.c:5655
rb_enable_interrupt
static void rb_enable_interrupt(void)
Definition: signal.c:580
eval_intern.h
rb_str_new_cstr
VALUE rb_str_new_cstr(const char *)
Definition: string.c:447
rb_threadptr_signal_raise
void rb_threadptr_signal_raise(rb_thread_t *th, int sig)
Definition: thread.c:2007
rb_iv_get
VALUE rb_iv_get(VALUE, const char *)
Definition: variable.c:2583
siglist
static struct signals siglist[]
RUBY_NSIG
#define RUBY_NSIG
Definition: vm_core.h:57
OBJ_TAINTED
#define OBJ_TAINTED(x)
ruby_sigaction_t
RETSIGTYPE ruby_sigaction_t(int)
Definition: signal.c:445
TYPE
#define TYPE(x)
rb_signal_exec
void rb_signal_exec(rb_thread_t *th, int sig)
Definition: signal.c:712
ruby_enable_coredump
#define ruby_enable_coredump
Definition: signal.c:1093
RSTRING_PTR
#define RSTRING_PTR(str)
kill
int kill(int, int)
Definition: win32.c:4079
NIL_P
NIL_P(eventloop_thread)
Definition: tcltklib.c:4068
safe
int safe
Definition: tcltklib.c:6404
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
SIGKILL
#define SIGKILL
Definition: win32.h:463
SafeStringValue
#define SafeStringValue(v)
rb_ary_new3
VALUE rb_ary_new3(long n,...)
Definition: array.c:432
rb_eSecurityError
VALUE rb_eSecurityError
Definition: error.c:520
rb_str_new2
#define rb_str_new2
esignal_signo
static VALUE esignal_signo(VALUE self)
Definition: signal.c:306
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1526
state
int state
Definition: tcltklib.c:1462
RB_UNUSED_VAR
#define RB_UNUSED_VAR(x)
rb_thread_struct
Definition: vm_core.h:493
args
VALUE VALUE args
Definition: tcltklib.c:2561
trap_handler
static sighandler_t trap_handler(VALUE *cmd, int sig)
Definition: signal.c:803
TRAP_INTERRUPT_MASK
Definition: vm_core.h:912
NORETURN
#define NORETURN(x)
Definition: ruby.h:31
ruby_atomic_compare_and_swap
rb_atomic_t ruby_atomic_compare_and_swap(rb_atomic_t *ptr, rb_atomic_t cmp, rb_atomic_t newval)
Definition: signal.c:36
sig_signame
static VALUE sig_signame(VALUE recv, VALUE signo)
Definition: signal.c:230
posix_signal
sighandler_t posix_signal(int signum, sighandler_t handler)
Definition: missing-pips.c:43
TH_POP_TAG
#define TH_POP_TAG()
Definition: eval_intern.h:101
sighandler_t
RETSIGTYPE(* sighandler_t)(int)
Definition: signal.c:440
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:479
ruby_disable_gc_stress
int ruby_disable_gc_stress
Definition: gc.c:336
reserved_signal_p
static int reserved_signal_p(int signo)
Definition: signal.c:931
ATOMIC_DEC
#define ATOMIC_DEC(var)
Definition: ruby_atomic.h:102
rb_thread_wakeup_timer_thread
void rb_thread_wakeup_timer_thread(void)
EXEC_TAG
#define EXEC_TAG()
Definition: eval_intern.h:113
ruby_atomic.h
Qnil
#define Qnil
Definition: tcltklib.c:1896
StringValuePtr
#define StringValuePtr(v)
val
#define val
Definition: tcltklib.c:1949
signals::signo
int signo
Definition: signal.c:57
str
static VALUE char * str
Definition: tcltklib.c:3547
sighandler
static RETSIGTYPE sighandler(int sig)
Definition: signal.c:549
JUMP_TAG
#define JUMP_TAG(st)
Definition: eval_intern.h:120
signals
Definition: signal.c:55
pthread_sigmask
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
Definition: missing-pips.c:22
install_sighandler
static void install_sighandler(int signum, sighandler_t handler)
Definition: signal.c:1048
RSTRING_LEN
#define RSTRING_LEN(str)
FIX2INT
#define FIX2INT(x)
INT2FIX
#define INT2FIX(i)
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Definition: object.c:2417
signal.h
T_STRING
#define T_STRING
rb_trap_exit
void rb_trap_exit(void)
Definition: signal.c:700
rb_call_super
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:273
err
int err
Definition: win32.c:87
default_handler
static sighandler_t default_handler(int sig)
Definition: signal.c:754
sig_trap
static VALUE sig_trap(int argc, VALUE *argv)
Definition: signal.c:992
rb_vm_struct::safe
int safe
Definition: vm_core.h:373
argv
VALUE * argv
Definition: tcltklib.c:1971
signm2signo
static int signm2signo(const char *nm)
Definition: signal.c:195
rb_hash_aset
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
rb_define_module_function
void rb_define_module_function(VALUE module, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a module function for module.
Definition: class.c:1512
errno
int errno
Init_signal
void Init_signal(void)
Definition: signal.c:1134
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1270
rb_proc_t
Definition: vm_core.h:668
s
register char * s
Definition: os2.c:56
void
VP_EXPORT void
Definition: bigdecimal.c:5083
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
rb_eInterrupt
VALUE rb_eInterrupt
Definition: error.c:506
ruby_signal_name
const char * ruby_signal_name(int)
Definition: signal.c:237
rb_f_kill
VALUE rb_f_kill(int, VALUE *)
Definition: signal.c:364
vm_core.h
T_FIXNUM
#define T_FIXNUM
argc
int argc
Definition: tcltklib.c:1970
rb_alias
void rb_alias(VALUE, ID, ID)
Definition: vm_method.c:1182
signo2signm
static const char * signo2signm(int no)
Definition: signal.c:206
rb_disable_interrupt
static void rb_disable_interrupt(void)
Definition: signal.c:570
rb_bug_errno
void rb_bug_errno(const char *mesg, int errno_arg)
Definition: error.c:313
TH_PUSH_TAG
#define TH_PUSH_TAG(th)
Definition: eval_intern.h:94
cmd
const char * cmd
Definition: tcltklib.c:278
NSIG
#define NSIG
Definition: vm_core.h:54
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:1899
ptr
return ptr
Definition: tcltklib.c:784
ATOMIC_INC
#define ATOMIC_INC(var)
Definition: ruby_atomic.h:101
msg
volatile VALUE msg
Definition: tcltklib.c:3100
T_SYMBOL
#define T_SYMBOL
size
int size
Definition: encoding.c:52
CHECK_STACK_OVERFLOW
#define CHECK_STACK_OVERFLOW()
Definition: signal.c:621
SYMBOL_P
#define SYMBOL_P(x)
signal
sighandler_t signal(int signum, sighandler_t handler)
Qundef
#define Qundef
rb_thread_struct::interrupt_mask
unsigned long interrupt_mask
Definition: vm_core.h:555
ruby_sig_finalize
void ruby_sig_finalize(void)
Definition: signal.c:1080
rb_signal_buff_size
int rb_signal_buff_size(void)
Definition: signal.c:560
INT2NUM
#define INT2NUM(x)
esignal_init
static VALUE esignal_init(int argc, VALUE *argv, VALUE self)
Definition: signal.c:252
signal_buff
static struct @138 signal_buff
ruby_default_signal
void ruby_default_signal(int)
Definition: signal.c:323
rb_atomic_t
int rb_atomic_t
Definition: ruby_atomic.h:93
rb_safe_level
#define rb_safe_level()
Definition: tcltklib.c:94
rb_vm_struct
Definition: vm_core.h:337
NUM2INT
#define NUM2INT(x)
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:234
trap_signm
static int trap_signm(VALUE vsig)
Definition: signal.c:868
rb_id2name
const char * rb_id2name(ID id)
Definition: ripper.c:17005
cnt
int cnt
Definition: tcltklib.c:6149
rb_check_arity
#define rb_check_arity(argc, min, max)
killpg
#define killpg(pg, sig)
ruby_signal
#define ruby_signal(sig, handler)
Definition: signal.c:534
VALUE
unsigned long VALUE
Definition: ripper.y:104
rb_sigaltstack_size
int rb_sigaltstack_size(void)
rb_define_module
VALUE rb_define_module(const char *name)
Definition: class.c:617
rb_intern
#define rb_intern(str)
NULL
#define NULL
Definition: _sdbm.c:103
rb_get_next_signal
int rb_get_next_signal(void)
Definition: signal.c:590
name
const char * name
Definition: nkf.c:208
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:1508
GET_THREAD
static rb_thread_t * GET_THREAD(void)
Definition: vm_core.h:883
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
SYM2ID
#define SYM2ID(x)
rb_vm_struct::trap_list
struct rb_vm_struct::@152 trap_list[RUBY_NSIG]
rb_eArgError
VALUE rb_eArgError
Definition: error.c:512
cmp
static ID cmp
Definition: compar.c:16
ruby_atomic_exchange
rb_atomic_t ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val)
Definition: signal.c:28
rb_threadptr_signal_exit
void rb_threadptr_signal_exit(rb_thread_t *th)
Definition: thread.c:2017
SIGINT
#define SIGINT
Definition: win32.h:460
GET_VM
#define GET_VM()
Definition: vm_core.h:876