Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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