[#30743] 大きな数の大まかな割り算 — Yukihiro Matsumoto <matz@...>

まつもと ゆきひろです

17 messages 2007/05/01

[#30827] Supporting Fiber — SASADA Koichi <ko1@...>

 ささだです。

22 messages 2007/05/27

[ruby-dev:30830] trap in 1.9

From: Nobuyoshi Nakada <nobu@...>
Date: 2007-05-28 06:55:49 UTC
List: ruby-dev #30830
なかだです。

[ruby-dev:30820]を試していて気づいたのですが、1.9で以下のコード
がSEGVします。Qundefを返しているようです。

  p trap(:INT, trap(:INT, "EXIT"))

また、trap(:EXIT)だけは任意の文字列を渡せるままになっていますが、
やはりSEGVします。

  trap(:EXIT, "p")

ついでに、引数のチェックを先に済ますようにしてみました。


Index: signal.c
===================================================================
--- signal.c	(revision 12396)
+++ signal.c	(working copy)
@@ -375,5 +375,4 @@ rb_f_kill(int argc, VALUE *argv)
 static struct {
     VALUE cmd;
-    int safe;
 } trap_list[NSIG];
 static rb_atomic_t trap_pending_list[NSIG];
@@ -545,4 +544,13 @@ sigpipe(int sig)
 #endif
 
+static void
+signal_exec(VALUE cmd, int sig)
+{
+    rb_proc_t *proc;
+    VALUE signum = INT2FIX(sig);
+    GetProcPtr(cmd, proc);
+    th_invoke_proc(GET_THREAD(), proc, proc->block.self, 1, &signum);
+}
+
 void
 rb_trap_exit(void)
@@ -553,5 +561,5 @@ rb_trap_exit(void)
 
 	trap_list[0].cmd = 0;
-	rb_eval_cmd(trap_exit, rb_ary_new3(1, INT2FIX(0)), trap_list[0].safe);
+	signal_exec(trap_exit, 0);
     }
 #endif
@@ -594,8 +602,5 @@ rb_signal_exec(rb_thread_t *th, int sig)
     }
     else {
-	rb_proc_t *proc;
-	VALUE signum = INT2FIX(sig);
-	GetProcPtr(cmd, proc);
-	th_invoke_proc(th, proc, proc->block.self, 1, &signum);
+	signal_exec(cmd, sig);
     }
 }
@@ -625,21 +630,20 @@ struct trap_arg {
 # endif
 #endif
-    VALUE sig, cmd;
+    int sig;
+    sighandler_t func;
+    VALUE cmd;
 };
 
-static VALUE
-trap(struct trap_arg *arg)
+static sighandler_t
+trap_handler(VALUE *cmd)
 {
-    sighandler_t func, oldfunc;
-    VALUE command, oldcmd;
-    int sig = -1;
-    const char *s;
+    sighandler_t func = 0;
+    VALUE command;
 
-    func = sighandler;
-    if (NIL_P(arg->cmd)) {
+    if (NIL_P(*cmd)) {
 	func = SIG_IGN;
     }
     else {
-	command = rb_check_string_type(arg->cmd);
+	command = rb_check_string_type(*cmd);
 	if (!NIL_P(command)) {
 	    SafeStringValue(command);	/* taint check */
@@ -666,29 +670,47 @@ trap(struct trap_arg *arg)
 	      case 4:
 		if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) {
-		    arg->cmd = Qundef;
+		    func = sighandler;
+		    *cmd = Qundef;
 		}
 		break;
 	    }
+	    if (!func) {
+		rb_raise(rb_eArgError, "wrong trap - %s", RSTRING_PTR(command));
+	    }
+	}
+	else {
+	    rb_proc_t *proc;
+	    GetProcPtr(*cmd, proc);
+	    func = sighandler;
 	}
     }
     if (func == SIG_IGN || func == SIG_DFL) {
-	command = 0;
-    }
-    else {
-	command = arg->cmd;
+	*cmd = 0;
     }
 
-    switch (TYPE(arg->sig)) {
+    return func;
+}
+
+static int
+trap_signm(VALUE vsig)
+{
+    int sig = -1;
+    const char *s;
+
+    switch (TYPE(vsig)) {
       case T_FIXNUM:
-	sig = FIX2INT(arg->sig);
+	sig = FIX2INT(vsig);
+	if (sig < 0 || sig >= NSIG) {
+	    rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
+	}
 	break;
 
       case T_SYMBOL:
-	s = rb_id2name(SYM2ID(arg->sig));
+	s = rb_id2name(SYM2ID(vsig));
 	if (!s) rb_raise(rb_eArgError, "bad signal");
 	goto str_signal;
 
-      case T_STRING:
-	s = RSTRING_PTR(arg->sig);
+      default:
+	s = StringValuePtr(vsig);
 
       str_signal:
@@ -700,7 +722,4 @@ trap(struct trap_arg *arg)
     }
 
-    if (sig < 0 || sig >= NSIG) {
-	rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
-    }
 #if defined(HAVE_SETITIMER)
     if (sig == SIGVTALRM) {
@@ -708,4 +727,10 @@ trap(struct trap_arg *arg)
     }
 #endif
+    return sig;
+}
+
+static sighandler_t
+default_handler(sighandler_t func, int sig)
+{
     if (func == SIG_DFL) {
 	switch (sig) {
@@ -748,14 +773,29 @@ trap(struct trap_arg *arg)
 	}
     }
+
+    return func;
+}
+
+static VALUE
+trap(struct trap_arg *arg)
+{
+    sighandler_t oldfunc, func = arg->func;
+    VALUE oldcmd, command = arg->cmd;
+    int sig = arg->sig;
+
     oldfunc = ruby_signal(sig, func);
     oldcmd = trap_list[sig].cmd;
-    if (!oldcmd) {
+    switch (oldcmd) {
+      case 0:
 	if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
 	else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
 	else oldcmd = Qnil;
+	break;
+      case Qundef:
+	oldcmd = rb_str_new2("EXIT");
+	break;
     }
 
     trap_list[sig].cmd = command;
-    trap_list[sig].safe = rb_safe_level();
     /* enable at least specified signal. */
 #ifndef _WIN32
@@ -834,10 +874,12 @@ sig_trap(int argc, VALUE *argv)
     }
 
-    arg.sig = argv[0];
+    arg.sig = trap_signm(argv[0]);
     if (argc == 1) {
 	arg.cmd = rb_block_proc();
+	arg.func = sighandler;
     }
     else if (argc == 2) {
 	arg.cmd = argv[1];
+	arg.func = default_handler(trap_handler(&arg.cmd), arg.sig);
     }
 


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread

Prev Next