summaryrefslogtreecommitdiff
path: root/signal.c
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-06-23 15:02:21 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-06-23 15:02:21 +0000
commita5b0009c05edc3f9e7e09a085323c7b96ed0b8e0 (patch)
treeb7a2653e06742f205df815b1cd5fb0d5e9e0feb0 /signal.c
parent9f982bd59d6e3e5e4c2c5ca20bdef79df4f8b5c0 (diff)
merge revision(s) r46194: [Backport #9835]
* signal.c (signal_exec): ignore immediate cmd for SIG_IGN * signal.c (trap_handler): set cmd to true for SIG_IGN * signal.c (trap): handle nil and true values for oldcmd [Bug #9835] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_1@46520 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'signal.c')
-rw-r--r--signal.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/signal.c b/signal.c
index d82f4c7e2b..3c6b96737f 100644
--- a/signal.c
+++ b/signal.c
@@ -740,6 +740,15 @@ signal_exec(VALUE cmd, int safe, int sig)
volatile unsigned long old_interrupt_mask = cur_th->interrupt_mask;
int state;
+ /*
+ * workaround the following race:
+ * 1. signal_enque queues signal for execution
+ * 2. user calls trap(sig, "IGNORE"), setting SIG_IGN
+ * 3. rb_signal_exec runs on queued signal
+ */
+ if (IMMEDIATE_P(cmd))
+ return;
+
cur_th->interrupt_mask |= TRAP_INTERRUPT_MASK;
TH_PUSH_TAG(cur_th);
if ((state = EXEC_TAG()) == 0) {
@@ -891,7 +900,7 @@ trap_handler(VALUE *cmd, int sig)
if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) {
sig_ign:
func = SIG_IGN;
- *cmd = 0;
+ *cmd = Qtrue;
}
else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
sig_dfl:
@@ -972,10 +981,13 @@ trap(int sig, sighandler_t func, VALUE command)
oldcmd = vm->trap_list[sig].cmd;
switch (oldcmd) {
case 0:
+ case Qtrue:
if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
else oldcmd = Qnil;
break;
+ case Qnil:
+ break;
case Qundef:
oldcmd = rb_str_new2("EXIT");
break;