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