Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 788 lines (701 sloc) 17.846 kb
9c1d230 committing experimental branch content
Laurent Sansonetti authored
1 /**********************************************************************
2
3 signal.c -
4
5 $Author: mame $
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
153d145 don't install stupid handlers on some signals
Laurent Sansonetti authored
14 // TODO: rewrite me!
15
9c1d230 committing experimental branch content
Laurent Sansonetti authored
16 #include "ruby/ruby.h"
17 #include "ruby/signal.h"
18 #include "ruby/node.h"
19 #include "id.h"
cb65416 the great schism, part I
Laurent Sansonetti authored
20 #include "vm.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored
21 #include <signal.h>
22 #include <stdio.h>
23
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
24 #define USE_DEFAULT_HANDLER (void (*)(int))-1
9c1d230 committing experimental branch content
Laurent Sansonetti authored
25
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
26 static RETSIGTYPE sighandler(int sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
27
28 static const struct signals {
29 const char *signm;
30 int signo;
31 } siglist [] = {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
32 {"EXIT", 0},
33 {"HUP", SIGHUP},
34 {"INT", SIGINT},
35 {"QUIT", SIGQUIT},
36 {"ILL", SIGILL},
37 {"TRAP", SIGTRAP},
38 {"IOT", SIGIOT},
39 {"ABRT", SIGABRT},
40 {"EMT", SIGEMT},
41 {"FPE", SIGFPE},
42 {"KILL", SIGKILL},
43 {"BUS", SIGBUS},
44 {"SEGV", SIGSEGV},
45 {"SYS", SIGSYS},
46 {"PIPE", SIGPIPE},
47 {"ALRM", SIGALRM},
48 {"TERM", SIGTERM},
49 {"URG", SIGURG},
50 {"STOP", SIGSTOP},
51 {"TSTP", SIGTSTP},
52 {"CONT", SIGCONT},
53 {"CHLD", SIGCHLD},
54 {"CLD", SIGCHLD},
55 {"TTIN", SIGTTIN},
56 {"TTOU", SIGTTOU},
57 {"IO", SIGIO},
58 {"XCPU", SIGXCPU},
59 {"XFSZ", SIGXFSZ},
9c1d230 committing experimental branch content
Laurent Sansonetti authored
60 {"VTALRM", SIGVTALRM},
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
61 {"PROF", SIGPROF},
62 {"WINCH", SIGWINCH},
63 {"INFO", SIGINFO},
64 {"USR1", SIGUSR1},
65 {"USR2", SIGUSR2},
9c1d230 committing experimental branch content
Laurent Sansonetti authored
66 {NULL, 0}
67 };
68
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
69 static const struct trap_handlers {
70 const char *command;
71 VALUE new_cmd_value;
72 sighandler_t handler;
73 } gl_trap_handlers[] = {
74 {"SYSTEM_DEFAULT", 0, SIG_DFL},
75 {"SIG_IGN", 0, SIG_IGN},
76 {"IGNORE", 0, SIG_IGN},
77 {"", 0, SIG_IGN},
78 {"SIG_DFL", 0, USE_DEFAULT_HANDLER},
79 {"DEFAULT", 0, USE_DEFAULT_HANDLER},
80 {"EXIT", Qundef, sighandler},
81 {NULL, 0}
82 };
83
9c1d230 committing experimental branch content
Laurent Sansonetti authored
84 static int
85 signm2signo(const char *nm)
86 {
87 const struct signals *sigs;
88
89 for (sigs = siglist; sigs->signm; sigs++)
90 if (strcmp(sigs->signm, nm) == 0)
91 return sigs->signo;
92 return 0;
93 }
94
95 static const char*
96 signo2signm(int no)
97 {
98 const struct signals *sigs;
99
100 for (sigs = siglist; sigs->signm; sigs++)
101 if (sigs->signo == no)
102 return sigs->signm;
103 return 0;
104 }
105
106 const char *
107 ruby_signal_name(int no)
108 {
109 return signo2signm(no);
110 }
111
112 /*
113 * call-seq:
114 * SignalException.new(sig) => signal_exception
115 *
116 * Construct a new SignalException object. +sig+ should be a known
117 * signal name, or a signal number.
118 */
119
120 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
121 esignal_init(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
122 {
123 int argnum = 1;
124 VALUE sig = Qnil;
125 int signo;
126 const char *signm;
127
128 if (argc > 0) {
129 sig = rb_check_to_integer(argv[0], "to_int");
130 if (!NIL_P(sig)) argnum = 2;
131 else sig = argv[0];
132 }
133 if (argc < 1 || argnum < argc) {
134 rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
135 argc, argnum);
136 }
137 if (argnum == 2) {
138 signo = NUM2INT(sig);
139 if (signo < 0 || signo > NSIG) {
140 rb_raise(rb_eArgError, "invalid signal number (%d)", signo);
141 }
142 if (argc > 1) {
143 sig = argv[1];
144 }
145 else {
146 signm = signo2signm(signo);
147 if (signm) {
148 sig = rb_sprintf("SIG%s", signm);
149 }
150 else {
151 sig = rb_sprintf("SIG%u", signo);
152 }
153 }
154 }
155 else {
156 signm = SYMBOL_P(sig) ? rb_sym2name(sig) : StringValuePtr(sig);
157 if (strncmp(signm, "SIG", 3) == 0) signm += 3;
158 signo = signm2signo(signm);
159 if (!signo) {
160 rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm);
161 }
162 sig = rb_sprintf("SIG%s", signm);
163 }
164 //rb_call_super(1, &sig);
165 rb_vm_call(self, selInitialize2, 1, &sig, true);
166 rb_iv_set(self, "signo", INT2NUM(signo));
167
168 return self;
169 }
170
171 /*
172 * call-seq:
173 * signal_exception.signo => num
174 *
175 * Returns a signal number.
176 */
177
178 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
179 esignal_signo(VALUE self, SEL sel)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
180 {
181 return rb_iv_get(self, "signo");
182 }
183
184 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
185 interrupt_init(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
186 {
187 VALUE args[2];
188
189 args[0] = INT2FIX(SIGINT);
190 rb_scan_args(argc, argv, "01", &args[1]);
191 return rb_vm_call(self, selInitialize2, 2, args, true);
192 }
193
194 void
195 ruby_default_signal(int sig)
196 {
197 #ifndef MACOS_UNUSE_SIGNAL
198 signal(sig, SIG_DFL);
199 raise(sig);
200 #endif
201 }
202
203 /*
204 * call-seq:
205 * Process.kill(signal, pid, ...) => fixnum
206 *
207 * Sends the given signal to the specified process id(s), or to the
208 * current process if _pid_ is zero. _signal_ may be an
209 * integer signal number or a POSIX signal name (either with or without
210 * a +SIG+ prefix). If _signal_ is negative (or starts
211 * with a minus sign), kills process groups instead of
212 * processes. Not all signals are available on all platforms.
213 *
214 * pid = fork do
215 * Signal.trap("HUP") { puts "Ouch!"; exit }
216 * # ... do some work ...
217 * end
218 * # ...
219 * Process.kill("HUP", pid)
220 * Process.wait
221 *
222 * <em>produces:</em>
223 *
224 * Ouch!
225 */
226
227 VALUE
e53e3cb ported process.c to the new runtime API
Laurent Sansonetti authored
228 rb_f_kill(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
229 {
230 int negative = 0;
231 int sig;
232 int i;
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
233 int type;
234 const char *s = NULL;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
235
236 rb_secure(2);
237 if (argc < 2)
238 rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)");
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
239
240 type = TYPE(argv[0]);
241 if (type == T_FIXNUM) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
242 sig = FIX2INT(argv[0]);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
243 }
244 else {
245 if (type == T_SYMBOL) {
246 s = rb_sym2name(argv[0]);
247 if (!s)
248 rb_raise(rb_eArgError, "bad signal");
9c1d230 committing experimental branch content
Laurent Sansonetti authored
249 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
250 else if (type == T_STRING) {
251 s = RSTRING_PTR(argv[0]);
252 if (s[0] == '-') {
253 negative++;
254 s++;
255 }
256 }
257 else {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
258 VALUE str;
259 str = rb_check_string_type(argv[0]);
260 if (!NIL_P(str)) {
261 s = RSTRING_PTR(str);
262 }
263 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
264 if (s == NULL)
265 rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0]));
266
267 if (strncmp("SIG", s, 3) == 0)
268 s += 3;
269 if ((sig = signm2signo(s)) == 0)
270 rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
271 if (negative)
272 sig = -sig;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
273 }
274
275 if (sig < 0) {
276 sig = -sig;
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
277 for (i = 1; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
278 if (killpg(NUM2PIDT(argv[i]), sig) < 0)
279 rb_sys_fail(0);
280 }
281 }
282 else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
283 for (i = 1; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
284 if (kill(NUM2PIDT(argv[i]), sig) < 0)
285 rb_sys_fail(0);
286 }
287 }
288 rb_thread_polling();
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
289 return INT2FIX(i - 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
290 }
291
292 rb_atomic_t rb_trap_pending;
293 rb_atomic_t rb_trap_immediate;
294 int rb_prohibit_interrupt = 1;
295
296 VALUE
297 rb_get_trap_cmd(int sig)
298 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
299 return rb_vm_trap_cmd_for_signal(sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
300 }
301
302 void
303 rb_gc_mark_trap_list(void)
304 {
305 #ifndef MACOS_UNUSE_SIGNAL
306 int i;
307
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
308 for (i = 0; i < NSIG; i++) {
309 if (rb_vm_trap_cmd_for_signal(i)) {
310 rb_gc_mark(rb_vm_trap_cmd_for_signal(i));
0c5e41a Courtesy of Jordan Breeding, a patch to build with Clang and llvm-gcc…
Patrick Thomson authored
311 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
312 }
313 #endif /* MACOS_UNUSE_SIGNAL */
314 }
315
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
316 sighandler_t
9c1d230 committing experimental branch content
Laurent Sansonetti authored
317 ruby_signal(int signum, sighandler_t handler)
318 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
319 struct sigaction sigact;
320 struct sigaction old;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
321
322 sigemptyset(&sigact.sa_mask);
323 sigact.sa_handler = handler;
324 sigact.sa_flags = 0;
325
326 if (signum == SIGCHLD && handler == SIG_IGN)
327 sigact.sa_flags |= SA_NOCLDWAIT;
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
328 if (signum == SIGSEGV)
329 sigact.sa_flags |= SA_ONSTACK;
330 if (sigaction(signum, &sigact, &old) < 0) {
331 if (errno != 0 && errno != EINVAL) {
332 rb_bug("sigaction error.\n");
333 }
334 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
335 return old.sa_handler;
336 }
337
338 sighandler_t
339 posix_signal(int signum, sighandler_t handler)
340 {
341 return ruby_signal(signum, handler);
342 }
343
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
344 static void signal_exec(VALUE cmd, int level, int sig);
345 static void rb_signal_exec(int sig);
346
9c1d230 committing experimental branch content
Laurent Sansonetti authored
347 static RETSIGTYPE
348 sighandler(int sig)
349 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
350 int olderrno = errno;
351 rb_signal_exec(sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
352 ruby_signal(sig, sighandler);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
353 errno = olderrno;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
354 }
355
356 #include <pthread.h>
357
358 void
359 rb_disable_interrupt(void)
360 {
361 sigset_t mask;
362 sigfillset(&mask);
363 sigdelset(&mask, SIGVTALRM);
364 sigdelset(&mask, SIGSEGV);
365 pthread_sigmask(SIG_SETMASK, &mask, NULL);
366 }
367
368 void
369 rb_enable_interrupt(void)
370 {
371 sigset_t mask;
372 sigemptyset(&mask);
373 pthread_sigmask(SIG_SETMASK, &mask, NULL);
374 }
375
376 static RETSIGTYPE
377 sigbus(int sig)
378 {
379 rb_bug("Bus Error");
380 }
381
382 static int segv_received = 0;
383 static RETSIGTYPE
384 sigsegv(int sig)
385 {
386 if (segv_received) {
387 fprintf(stderr, "SEGV recieved in SEGV handler\n");
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
388 exit(EXIT_FAILURE);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
389 }
390 else {
391 segv_received = 1;
392 rb_bug("Segmentation fault");
393 }
394 }
395
396 static RETSIGTYPE
397 sigpipe(int sig)
398 {
399 /* do nothing */
400 }
401
402 static void
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
403 signal_exec(VALUE cmd, int level, int sig)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
404 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
405 VALUE signum = INT2NUM(sig);
406 rb_eval_cmd(cmd, rb_ary_new3(1, signum), level);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
407 }
408
409 void
410 rb_trap_exit(void)
411 {
412 #ifndef MACOS_UNUSE_SIGNAL
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
413 VALUE trap_exit;
414 int safe;
415
416 trap_exit = rb_vm_trap_cmd_for_signal(0);
417 if (trap_exit != (VALUE)NULL) {
418 safe = rb_vm_trap_level_for_signal(0);
419 rb_vm_set_trap_for_signal((VALUE)0, safe, 0);
420 signal_exec(trap_exit, safe, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
421 }
422 #endif
423 }
424
425 static void
426 rb_signal_exec(int sig)
427 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
428 /* rb_vm_thread_t *t; */
429 /* VALUE exc; */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
430 VALUE cmd = rb_get_trap_cmd(sig);
431
432 if (cmd == 0) {
433 switch (sig) {
434 case SIGINT:
435 rb_interrupt();
436 break;
437 case SIGHUP:
438 case SIGQUIT:
439 case SIGTERM:
440 case SIGALRM:
441 case SIGUSR1:
442 case SIGUSR2:
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
443 /* t = GetThreadPtr(rb_vm_main_thread()); */
444 /* exc = rb_exc_new2(rb_eSignal, ruby_signal_name(sig)); */
445 /* rb_vm_thread_raise(t, exc); */
446 /* rb_raise(rb_eSignal, "%s", signo2signm(sig)); */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
447 break;
448 }
449 }
450 else if (cmd == Qundef) {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
451 //rb_thread_signal_exit(th);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
452 }
453 else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
454 signal_exec(cmd, rb_vm_trap_level_for_signal(sig), sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
455 }
456 }
457
458 struct trap_arg {
459 int sig;
460 sighandler_t func;
461 VALUE cmd;
462 };
463
464 static sighandler_t
465 default_handler(int sig)
466 {
467 sighandler_t func;
468 switch (sig) {
469 case SIGINT:
470 case SIGHUP:
471 case SIGQUIT:
472 case SIGTERM:
473 case SIGALRM:
474 case SIGUSR1:
475 case SIGUSR2:
476 func = sighandler;
477 break;
478 case SIGBUS:
479 func = sigbus;
480 break;
481 case SIGSEGV:
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
482 func = (sighandler_t)sigsegv;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
483 break;
484 case SIGPIPE:
485 func = sigpipe;
486 break;
487 default:
488 func = SIG_DFL;
489 break;
490 }
491
492 return func;
493 }
494
495 static sighandler_t
496 trap_handler(VALUE *cmd, int sig)
497 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
498 sighandler_t func = sighandler;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
499 VALUE command;
500
501 if (NIL_P(*cmd)) {
502 func = SIG_IGN;
503 }
504 else {
505 command = rb_check_string_type(*cmd);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
506 if (NIL_P(command) && SYMBOL_P(*cmd)) {
507 command = rb_id2str(SYM2ID(*cmd));
508 if (!command) rb_raise(rb_eArgError, "bad handler");
509 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
510 if (!NIL_P(command)) {
511 SafeStringValue(command); /* taint check */
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
512 *cmd = command;
513 for (int i = 0; gl_trap_handlers[i].command != NULL; i++) {
514 if (strcmp(gl_trap_handlers[i].command, RSTRING_PTR(command)) == 0) {
515 func = gl_trap_handlers[i].handler;
516 if (func == USE_DEFAULT_HANDLER) {
517 func = default_handler(sig);
518 }
519 *cmd = gl_trap_handlers[i].new_cmd_value;
520 break;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
521 }
522 }
523 }
524 else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
525 /* func = sighandler; */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
526 }
527 }
528
529 return func;
530 }
531
532 static int
533 trap_signm(VALUE vsig)
534 {
535 int sig = -1;
536 const char *s;
537
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
538 if (TYPE(vsig) == T_FIXNUM) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
539 sig = FIX2INT(vsig);
540 if (sig < 0 || sig >= NSIG) {
541 rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
542 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
543 }
544 else {
545 if (TYPE(vsig) == T_SYMBOL) {
546 s = rb_sym2name(vsig);
547 if (s == NULL)
548 rb_raise(rb_eArgError, "bad signal");
549 }
550 else
551 s = StringValuePtr(vsig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
552
553 if (strncmp("SIG", s, 3) == 0)
554 s += 3;
555 sig = signm2signo(s);
556 if (sig == 0 && strcmp(s, "EXIT") != 0)
557 rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
558 }
559 return sig;
560 }
561
562 static VALUE
563 trap(struct trap_arg *arg)
564 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
565 sighandler_t oldfunc;
566 sighandler_t func = arg->func;
567 VALUE oldcmd;
568 VALUE command = arg->cmd;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
569 int sig = arg->sig;
570
571 oldfunc = ruby_signal(sig, func);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
572 oldcmd = rb_vm_trap_cmd_for_signal(sig);
573 if (oldcmd == 0) {
574 if (oldfunc == SIG_IGN)
575 oldcmd = rb_str_new2("IGNORE");
576 else if (oldfunc == sighandler)
577 oldcmd = rb_str_new2("DEFAULT");
578 else
579 oldcmd = Qnil;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
580 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
581 else if (oldcmd == Qundef)
582 oldcmd = rb_str_new2("EXIT");
9c1d230 committing experimental branch content
Laurent Sansonetti authored
583
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
584 // Assign trap to signal
585 rb_vm_set_trap_for_signal(command, rb_safe_level(), sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
586
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
587 return oldcmd;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
588 }
589
590 void
591 rb_trap_restore_mask(void)
592 {
593 }
594
595 /*
596 * call-seq:
597 * Signal.trap( signal, command ) => obj
598 * Signal.trap( signal ) {| | block } => obj
599 *
600 * Specifies the handling of signals. The first parameter is a signal
601 * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
602 * signal number. The characters ``SIG'' may be omitted from the
603 * signal name. The command or block specifies code to be run when the
604 * signal is raised.
605 * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
606 * will be ignored.
607 * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
608 * will be invoked.
609 * If the command is ``EXIT'', the script will be terminated by the signal.
610 * If the command is ``SYSTEM_DEFAULT'', the operating system's default
611 * handler will be invoked.
612 * Otherwise, the given command or block will be run.
613 * The special signal name ``EXIT'' or signal number zero will be
614 * invoked just prior to program termination.
615 * trap returns the previous handler for the given signal.
616 *
617 * Signal.trap(0, proc { puts "Terminating: #{$$}" })
618 * Signal.trap("CLD") { puts "Child died" }
619 * fork && Process.wait
620 *
621 * produces:
622 * Terminating: 27461
623 * Child died
624 * Terminating: 27460
625 */
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
626
9c1d230 committing experimental branch content
Laurent Sansonetti authored
627 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
628 sig_trap(VALUE rcv, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
629 {
630 struct trap_arg arg;
631
632 rb_secure(2);
633 if (argc == 0 || argc > 2) {
634 rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
635 }
636
637 arg.sig = trap_signm(argv[0]);
638 if (argc == 1) {
639 arg.cmd = rb_block_proc();
640 arg.func = sighandler;
641 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
642 else {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
643 arg.cmd = argv[1];
644 arg.func = trap_handler(&arg.cmd, arg.sig);
645 }
646
647 if (OBJ_TAINTED(arg.cmd)) {
648 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
649 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
650
9c1d230 committing experimental branch content
Laurent Sansonetti authored
651 return trap(&arg);
652 }
653
654 /*
655 * call-seq:
656 * Signal.list => a_hash
657 *
658 * Returns a list of signal names mapped to the corresponding
659 * underlying signal numbers.
660 *
661 * Signal.list #=> {"ABRT"=>6, "ALRM"=>14, "BUS"=>7, "CHLD"=>17, "CLD"=>17, "CONT"=>18, "FPE"=>8, "HUP"=>1, "ILL"=>4, "INT"=>2, "IO"=>29, "IOT"=>6, "KILL"=>9, "PIPE"=>13, "POLL"=>29, "PROF"=>27, "PWR"=>30, "QUIT"=>3, "SEGV"=>11, "STOP"=>19, "SYS"=>31, "TERM"=>15, "TRAP"=>5, "TSTP"=>20, "TTIN"=>21, "TTOU"=>22, "URG"=>23, "USR1"=>10, "USR2"=>12, "VTALRM"=>26, "WINCH"=>28, "XCPU"=>24, "XFSZ"=>25}
662 */
663 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
664 sig_list(VALUE rcv, SEL sel)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
665 {
666 VALUE h = rb_hash_new();
667 const struct signals *sigs;
668
669 for (sigs = siglist; sigs->signm; sigs++) {
670 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
671 }
672 return h;
673 }
674
675 static void
676 install_sighandler(int signum, sighandler_t handler)
677 {
678 sighandler_t old;
679
680 old = ruby_signal(signum, handler);
681 if (old != SIG_DFL) {
682 ruby_signal(signum, old);
683 }
684 }
685
686 #if defined(SIGCLD) || defined(SIGCHLD)
687 static void
688 init_sigchld(int sig)
689 {
690 sighandler_t oldfunc;
691
692 oldfunc = ruby_signal(sig, SIG_DFL);
693 if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
694 ruby_signal(sig, oldfunc);
695 } else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
696 rb_vm_set_trap_for_signal((VALUE)0, rb_safe_level(), sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
697 }
698 }
699 #endif
700
701 void
702 ruby_sig_finalize()
703 {
704 sighandler_t oldfunc;
705
706 oldfunc = ruby_signal(SIGINT, SIG_IGN);
707 if (oldfunc == sighandler) {
708 ruby_signal(SIGINT, SIG_DFL);
709 }
710 }
711
712 #ifdef RUBY_DEBUG_ENV
713 int ruby_enable_coredump = 0;
714 #endif
715
716 /*
717 * Many operating systems allow signals to be sent to running
718 * processes. Some signals have a defined effect on the process, while
719 * others may be trapped at the code level and acted upon. For
720 * example, your process may trap the USR1 signal and use it to toggle
721 * debugging, and may use TERM to initiate a controlled shutdown.
722 *
723 * pid = fork do
724 * Signal.trap("USR1") do
725 * $debug = !$debug
726 * puts "Debug now: #$debug"
727 * end
728 * Signal.trap("TERM") do
729 * puts "Terminating..."
730 * shutdown()
731 * end
732 * # . . . do some work . . .
733 * end
734 *
735 * Process.detach(pid)
736 *
737 * # Controlling program:
738 * Process.kill("USR1", pid)
739 * # ...
740 * Process.kill("USR1", pid)
741 * # ...
742 * Process.kill("TERM", pid)
743 *
744 * produces:
745 * Debug now: true
746 * Debug now: false
747 * Terminating...
748 *
749 * The list of available signal names and their interpretation is
750 * system dependent. Signal delivery semantics may also vary between
751 * systems; in particular signal delivery may not always be reliable.
752 */
753 void
754 Init_signal(void)
755 {
756 #ifndef MACOS_UNUSE_SIGNAL
757 VALUE mSignal = rb_define_module("Signal");
758
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
759 rb_objc_define_module_function(rb_mKernel, "trap", sig_trap, -1);
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
760 rb_objc_define_method(*(VALUE *)mSignal, "trap", sig_trap, -1);
761 rb_objc_define_method(*(VALUE *)mSignal, "list", sig_list, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
762
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
763 rb_objc_define_method(rb_eSignal, "initialize", esignal_init, -1);
764 rb_objc_define_method(rb_eSignal, "signo", esignal_signo, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
765 rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
766 rb_objc_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
767
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
768 /* install_sighandler(SIGINT, sighandler); */
769 /* install_sighandler(SIGHUP, sighandler); */
770 /* install_sighandler(SIGQUIT, sighandler); */
771 /* install_sighandler(SIGTERM, sighandler); */
772 /* install_sighandler(SIGALRM, sighandler); */
773 /* install_sighandler(SIGUSR1, sighandler); */
774 /* install_sighandler(SIGUSR2, sighandler); */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
775
776 #ifdef RUBY_DEBUG_ENV
777 if (!ruby_enable_coredump)
778 #endif
779 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
780 install_sighandler(SIGBUS, sigbus);
781 install_sighandler(SIGSEGV, sigsegv);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
782 }
783 install_sighandler(SIGPIPE, sigpipe);
784
785 init_sigchld(SIGCHLD);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
786 #endif /* !MACOS_UNUSE_SIGNAL */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
787 }
Something went wrong with that request. Please try again.