Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 739 lines (657 sloc) 16.976 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
d0898dd include/ruby/macruby.h -> macruby_internal.h
Laurent Sansonetti authored
16 #include "macruby_internal.h"
9c1d230 committing experimental branch content
Laurent Sansonetti authored
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 }
70ea0b5 per-vm method cache + misc fixes/improvements
Laurent Sansonetti authored
164 rb_vm_call_super(self, selInitialize2, 1, &sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
165 rb_iv_set(self, "signo", INT2NUM(signo));
166
167 return self;
168 }
169
170 /*
171 * call-seq:
172 * signal_exception.signo => num
173 *
174 * Returns a signal number.
175 */
176
177 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
178 esignal_signo(VALUE self, SEL sel)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
179 {
180 return rb_iv_get(self, "signo");
181 }
182
183 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
184 interrupt_init(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
185 {
186 VALUE args[2];
187
188 args[0] = INT2FIX(SIGINT);
189 rb_scan_args(argc, argv, "01", &args[1]);
70ea0b5 per-vm method cache + misc fixes/improvements
Laurent Sansonetti authored
190 return rb_vm_call_super(self, selInitialize2, 2, args);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
191 }
192
193 void
194 ruby_default_signal(int sig)
195 {
196 #ifndef MACOS_UNUSE_SIGNAL
197 signal(sig, SIG_DFL);
198 raise(sig);
199 #endif
200 }
201
202 /*
203 * call-seq:
204 * Process.kill(signal, pid, ...) => fixnum
205 *
206 * Sends the given signal to the specified process id(s), or to the
207 * current process if _pid_ is zero. _signal_ may be an
208 * integer signal number or a POSIX signal name (either with or without
209 * a +SIG+ prefix). If _signal_ is negative (or starts
210 * with a minus sign), kills process groups instead of
211 * processes. Not all signals are available on all platforms.
212 *
213 * pid = fork do
214 * Signal.trap("HUP") { puts "Ouch!"; exit }
215 * # ... do some work ...
216 * end
217 * # ...
218 * Process.kill("HUP", pid)
219 * Process.wait
220 *
221 * <em>produces:</em>
222 *
223 * Ouch!
224 */
225
226 VALUE
e53e3cb ported process.c to the new runtime API
Laurent Sansonetti authored
227 rb_f_kill(VALUE self, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
228 {
229 int negative = 0;
230 int sig;
231 int i;
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
232 int type;
233 const char *s = NULL;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
234
235 rb_secure(2);
236 if (argc < 2)
237 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
238
239 type = TYPE(argv[0]);
240 if (type == T_FIXNUM) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
241 sig = FIX2INT(argv[0]);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
242 }
243 else {
244 if (type == T_SYMBOL) {
245 s = rb_sym2name(argv[0]);
246 if (!s)
247 rb_raise(rb_eArgError, "bad signal");
9c1d230 committing experimental branch content
Laurent Sansonetti authored
248 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
249 else if (type == T_STRING) {
250 s = RSTRING_PTR(argv[0]);
251 if (s[0] == '-') {
252 negative++;
253 s++;
254 }
255 }
256 else {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
257 VALUE str;
258 str = rb_check_string_type(argv[0]);
259 if (!NIL_P(str)) {
260 s = RSTRING_PTR(str);
261 }
262 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
263 if (s == NULL)
264 rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0]));
265
266 if (strncmp("SIG", s, 3) == 0)
267 s += 3;
268 if ((sig = signm2signo(s)) == 0)
269 rb_raise(rb_eArgError, "unsupported name `SIG%s'", s);
270 if (negative)
271 sig = -sig;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
272 }
273
274 if (sig < 0) {
275 sig = -sig;
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
276 for (i = 1; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
277 if (killpg(NUM2PIDT(argv[i]), sig) < 0)
278 rb_sys_fail(0);
279 }
280 }
281 else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
282 for (i = 1; i < argc; i++) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
283 if (kill(NUM2PIDT(argv[i]), sig) < 0)
284 rb_sys_fail(0);
285 }
286 }
287 rb_thread_polling();
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
288 return INT2FIX(i - 1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
289 }
290
291 VALUE
292 rb_get_trap_cmd(int sig)
293 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
294 return rb_vm_trap_cmd_for_signal(sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
295 }
296
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
297 sighandler_t
9c1d230 committing experimental branch content
Laurent Sansonetti authored
298 ruby_signal(int signum, sighandler_t handler)
299 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
300 struct sigaction sigact;
301 struct sigaction old;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
302
303 sigemptyset(&sigact.sa_mask);
304 sigact.sa_handler = handler;
305 sigact.sa_flags = 0;
306
307 if (signum == SIGCHLD && handler == SIG_IGN)
308 sigact.sa_flags |= SA_NOCLDWAIT;
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
309 if (signum == SIGSEGV)
310 sigact.sa_flags |= SA_ONSTACK;
311 if (sigaction(signum, &sigact, &old) < 0) {
312 if (errno != 0 && errno != EINVAL) {
313 rb_bug("sigaction error.\n");
314 }
315 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
316 return old.sa_handler;
317 }
318
319 sighandler_t
320 posix_signal(int signum, sighandler_t handler)
321 {
322 return ruby_signal(signum, handler);
323 }
324
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
325 static void signal_exec(VALUE cmd, int level, int sig);
326 static void rb_signal_exec(int sig);
327
9c1d230 committing experimental branch content
Laurent Sansonetti authored
328 static RETSIGTYPE
329 sighandler(int sig)
330 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
331 int olderrno = errno;
332 rb_signal_exec(sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
333 ruby_signal(sig, sighandler);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
334 errno = olderrno;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
335 }
336
337 #include <pthread.h>
338
339 void
340 rb_disable_interrupt(void)
341 {
342 sigset_t mask;
343 sigfillset(&mask);
344 sigdelset(&mask, SIGVTALRM);
345 sigdelset(&mask, SIGSEGV);
346 pthread_sigmask(SIG_SETMASK, &mask, NULL);
347 }
348
349 void
350 rb_enable_interrupt(void)
351 {
352 sigset_t mask;
353 sigemptyset(&mask);
354 pthread_sigmask(SIG_SETMASK, &mask, NULL);
355 }
356
357 static RETSIGTYPE
358 sigpipe(int sig)
359 {
360 /* do nothing */
361 }
362
363 static void
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
364 signal_exec(VALUE cmd, int level, int sig)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
365 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
366 VALUE signum = INT2NUM(sig);
367 rb_eval_cmd(cmd, rb_ary_new3(1, signum), level);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
368 }
369
370 void
371 rb_trap_exit(void)
372 {
7a4fd1b start cleaning up the public header files
Laurent Sansonetti authored
373 #if 0//ndef MACOS_UNUSE_SIGNAL
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
374 VALUE trap_exit;
375 int safe;
376
377 trap_exit = rb_vm_trap_cmd_for_signal(0);
378 if (trap_exit != (VALUE)NULL) {
379 safe = rb_vm_trap_level_for_signal(0);
380 rb_vm_set_trap_for_signal((VALUE)0, safe, 0);
381 signal_exec(trap_exit, safe, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
382 }
383 #endif
384 }
385
386 static void
387 rb_signal_exec(int sig)
388 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
389 /* rb_vm_thread_t *t; */
390 /* VALUE exc; */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
391 VALUE cmd = rb_get_trap_cmd(sig);
392
393 if (cmd == 0) {
394 switch (sig) {
395 case SIGINT:
396 rb_interrupt();
397 break;
398 case SIGHUP:
399 case SIGQUIT:
400 case SIGTERM:
401 case SIGALRM:
402 case SIGUSR1:
403 case SIGUSR2:
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
404 /* t = GetThreadPtr(rb_vm_main_thread()); */
405 /* exc = rb_exc_new2(rb_eSignal, ruby_signal_name(sig)); */
406 /* rb_vm_thread_raise(t, exc); */
407 /* rb_raise(rb_eSignal, "%s", signo2signm(sig)); */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
408 break;
409 }
410 }
411 else if (cmd == Qundef) {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
412 //rb_thread_signal_exit(th);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
413 }
414 else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
415 signal_exec(cmd, rb_vm_trap_level_for_signal(sig), sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
416 }
417 }
418
419 struct trap_arg {
420 int sig;
421 sighandler_t func;
422 VALUE cmd;
423 };
424
425 static sighandler_t
426 default_handler(int sig)
427 {
428 sighandler_t func;
429 switch (sig) {
430 case SIGINT:
431 case SIGHUP:
432 case SIGQUIT:
433 case SIGTERM:
434 case SIGALRM:
435 case SIGUSR1:
436 case SIGUSR2:
437 func = sighandler;
438 break;
439 case SIGPIPE:
440 func = sigpipe;
441 break;
442 default:
443 func = SIG_DFL;
444 break;
445 }
446
447 return func;
448 }
449
450 static sighandler_t
451 trap_handler(VALUE *cmd, int sig)
452 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
453 sighandler_t func = sighandler;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
454 VALUE command;
455
456 if (NIL_P(*cmd)) {
457 func = SIG_IGN;
458 }
459 else {
460 command = rb_check_string_type(*cmd);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
461 if (NIL_P(command) && SYMBOL_P(*cmd)) {
462 command = rb_id2str(SYM2ID(*cmd));
463 if (!command) rb_raise(rb_eArgError, "bad handler");
464 }
9c1d230 committing experimental branch content
Laurent Sansonetti authored
465 if (!NIL_P(command)) {
466 SafeStringValue(command); /* taint check */
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
467 *cmd = command;
468 for (int i = 0; gl_trap_handlers[i].command != NULL; i++) {
469 if (strcmp(gl_trap_handlers[i].command, RSTRING_PTR(command)) == 0) {
470 func = gl_trap_handlers[i].handler;
471 if (func == USE_DEFAULT_HANDLER) {
472 func = default_handler(sig);
473 }
474 *cmd = gl_trap_handlers[i].new_cmd_value;
475 break;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
476 }
477 }
478 }
479 else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
480 /* func = sighandler; */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
481 }
482 }
483
484 return func;
485 }
486
487 static int
488 trap_signm(VALUE vsig)
489 {
490 int sig = -1;
491 const char *s;
492
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
493 if (TYPE(vsig) == T_FIXNUM) {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
494 sig = FIX2INT(vsig);
495 if (sig < 0 || sig >= NSIG) {
496 rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
497 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
498 }
499 else {
500 if (TYPE(vsig) == T_SYMBOL) {
501 s = rb_sym2name(vsig);
502 if (s == NULL)
503 rb_raise(rb_eArgError, "bad signal");
504 }
505 else
506 s = StringValuePtr(vsig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
507
508 if (strncmp("SIG", s, 3) == 0)
509 s += 3;
510 sig = signm2signo(s);
511 if (sig == 0 && strcmp(s, "EXIT") != 0)
512 rb_raise(rb_eArgError, "unsupported signal SIG%s", s);
513 }
514 return sig;
515 }
516
517 static VALUE
518 trap(struct trap_arg *arg)
519 {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
520 sighandler_t oldfunc;
521 sighandler_t func = arg->func;
522 VALUE oldcmd;
523 VALUE command = arg->cmd;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
524 int sig = arg->sig;
525
526 oldfunc = ruby_signal(sig, func);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
527 oldcmd = rb_vm_trap_cmd_for_signal(sig);
528 if (oldcmd == 0) {
529 if (oldfunc == SIG_IGN)
530 oldcmd = rb_str_new2("IGNORE");
531 else if (oldfunc == sighandler)
532 oldcmd = rb_str_new2("DEFAULT");
533 else
534 oldcmd = Qnil;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
535 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
536 else if (oldcmd == Qundef)
537 oldcmd = rb_str_new2("EXIT");
9c1d230 committing experimental branch content
Laurent Sansonetti authored
538
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
539 // Assign trap to signal
540 rb_vm_set_trap_for_signal(command, rb_safe_level(), sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
541
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
542 return oldcmd;
9c1d230 committing experimental branch content
Laurent Sansonetti authored
543 }
544
545 void
546 rb_trap_restore_mask(void)
547 {
548 }
549
550 /*
551 * call-seq:
552 * Signal.trap( signal, command ) => obj
553 * Signal.trap( signal ) {| | block } => obj
554 *
555 * Specifies the handling of signals. The first parameter is a signal
556 * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
557 * signal number. The characters ``SIG'' may be omitted from the
558 * signal name. The command or block specifies code to be run when the
559 * signal is raised.
560 * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
561 * will be ignored.
562 * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
563 * will be invoked.
564 * If the command is ``EXIT'', the script will be terminated by the signal.
565 * If the command is ``SYSTEM_DEFAULT'', the operating system's default
566 * handler will be invoked.
567 * Otherwise, the given command or block will be run.
568 * The special signal name ``EXIT'' or signal number zero will be
569 * invoked just prior to program termination.
570 * trap returns the previous handler for the given signal.
571 *
572 * Signal.trap(0, proc { puts "Terminating: #{$$}" })
573 * Signal.trap("CLD") { puts "Child died" }
574 * fork && Process.wait
575 *
576 * produces:
577 * Terminating: 27461
578 * Child died
579 * Terminating: 27460
580 */
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
581
9c1d230 committing experimental branch content
Laurent Sansonetti authored
582 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
583 sig_trap(VALUE rcv, SEL sel, int argc, VALUE *argv)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
584 {
585 struct trap_arg arg;
586
587 rb_secure(2);
588 if (argc == 0 || argc > 2) {
589 rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}");
590 }
591
592 arg.sig = trap_signm(argv[0]);
593 if (argc == 1) {
594 arg.cmd = rb_block_proc();
595 arg.func = sighandler;
596 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
597 else {
9c1d230 committing experimental branch content
Laurent Sansonetti authored
598 arg.cmd = argv[1];
599 arg.func = trap_handler(&arg.cmd, arg.sig);
600 }
601
602 if (OBJ_TAINTED(arg.cmd)) {
603 rb_raise(rb_eSecurityError, "Insecure: tainted signal trap");
604 }
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
605
9c1d230 committing experimental branch content
Laurent Sansonetti authored
606 return trap(&arg);
607 }
608
609 /*
610 * call-seq:
611 * Signal.list => a_hash
612 *
613 * Returns a list of signal names mapped to the corresponding
614 * underlying signal numbers.
615 *
616 * 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}
617 */
618 static VALUE
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
619 sig_list(VALUE rcv, SEL sel)
9c1d230 committing experimental branch content
Laurent Sansonetti authored
620 {
621 VALUE h = rb_hash_new();
622 const struct signals *sigs;
623
624 for (sigs = siglist; sigs->signm; sigs++) {
625 rb_hash_aset(h, rb_str_new2(sigs->signm), INT2FIX(sigs->signo));
626 }
627 return h;
628 }
629
630 static void
631 install_sighandler(int signum, sighandler_t handler)
632 {
633 sighandler_t old;
634
635 old = ruby_signal(signum, handler);
636 if (old != SIG_DFL) {
637 ruby_signal(signum, old);
638 }
639 }
640
641 #if defined(SIGCLD) || defined(SIGCHLD)
642 static void
643 init_sigchld(int sig)
644 {
645 sighandler_t oldfunc;
646
647 oldfunc = ruby_signal(sig, SIG_DFL);
648 if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) {
649 ruby_signal(sig, oldfunc);
650 } else {
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
651 rb_vm_set_trap_for_signal((VALUE)0, rb_safe_level(), sig);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
652 }
653 }
654 #endif
655
656 void
657 ruby_sig_finalize()
658 {
659 sighandler_t oldfunc;
660
661 oldfunc = ruby_signal(SIGINT, SIG_IGN);
662 if (oldfunc == sighandler) {
663 ruby_signal(SIGINT, SIG_DFL);
664 }
665 }
666
667 #ifdef RUBY_DEBUG_ENV
668 int ruby_enable_coredump = 0;
669 #endif
670
671 /*
672 * Many operating systems allow signals to be sent to running
673 * processes. Some signals have a defined effect on the process, while
674 * others may be trapped at the code level and acted upon. For
675 * example, your process may trap the USR1 signal and use it to toggle
676 * debugging, and may use TERM to initiate a controlled shutdown.
677 *
678 * pid = fork do
679 * Signal.trap("USR1") do
680 * $debug = !$debug
681 * puts "Debug now: #$debug"
682 * end
683 * Signal.trap("TERM") do
684 * puts "Terminating..."
685 * shutdown()
686 * end
687 * # . . . do some work . . .
688 * end
689 *
690 * Process.detach(pid)
691 *
692 * # Controlling program:
693 * Process.kill("USR1", pid)
694 * # ...
695 * Process.kill("USR1", pid)
696 * # ...
697 * Process.kill("TERM", pid)
698 *
699 * produces:
700 * Debug now: true
701 * Debug now: false
702 * Terminating...
703 *
704 * The list of available signal names and their interpretation is
705 * system dependent. Signal delivery semantics may also vary between
706 * systems; in particular signal delivery may not always be reliable.
707 */
708 void
709 Init_signal(void)
710 {
711 #ifndef MACOS_UNUSE_SIGNAL
712 VALUE mSignal = rb_define_module("Signal");
713
cbe906e introduce rb_objc_define_module_function() which mimics the ruby spec
Laurent Sansonetti authored
714 rb_objc_define_module_function(rb_mKernel, "trap", sig_trap, -1);
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
715 rb_objc_define_method(*(VALUE *)mSignal, "trap", sig_trap, -1);
716 rb_objc_define_method(*(VALUE *)mSignal, "list", sig_list, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
717
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
718 rb_objc_define_method(rb_eSignal, "initialize", esignal_init, -1);
719 rb_objc_define_method(rb_eSignal, "signo", esignal_signo, 0);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
720 rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message"));
eab11cf ported to rb_objc_define_method()
Laurent Sansonetti authored
721 rb_objc_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
9c1d230 committing experimental branch content
Laurent Sansonetti authored
722
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
723 /* install_sighandler(SIGINT, sighandler); */
724 /* install_sighandler(SIGHUP, sighandler); */
725 /* install_sighandler(SIGQUIT, sighandler); */
726 /* install_sighandler(SIGTERM, sighandler); */
727 /* install_sighandler(SIGALRM, sighandler); */
728 /* install_sighandler(SIGUSR1, sighandler); */
729 /* install_sighandler(SIGUSR2, sighandler); */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
730
731 #ifdef RUBY_DEBUG_ENV
732 if (!ruby_enable_coredump)
733 #endif
734 install_sighandler(SIGPIPE, sigpipe);
735
736 init_sigchld(SIGCHLD);
71a58c5 - Some beginning to signal handling. It is not yet complete, as we c…
Thibault Martin-Lagardette authored
737 #endif /* !MACOS_UNUSE_SIGNAL */
9c1d230 committing experimental branch content
Laurent Sansonetti authored
738 }
Something went wrong with that request. Please try again.