Skip to content

Commit 7706aa1

Browse files
committed
merge revision(s) r45911,r45912,r45917,r45918,r45919: [Backport ruby#9820]
* signal.c (rb_f_kill): directly enqueue an ignored signal to self, except for SIGSEGV and SIGBUS. [ruby-dev:48203] [Bug ruby#9820] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_1@47345 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent a223ff8 commit 7706aa1

File tree

6 files changed

+106
-18
lines changed

6 files changed

+106
-18
lines changed

ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Tue Sep 2 02:08:12 2014 Nobuyoshi Nakada <[email protected]>
2+
3+
* signal.c (rb_f_kill): directly enqueue an ignored signal to self,
4+
except for SIGSEGV and SIGBUS. [ruby-dev:48203] [Bug #9820]
5+
16
Sun Aug 31 01:13:21 2014 Koichi Sasada <[email protected]>
27

38
* gc.c: change full GC timing to keep lower memory usage.

signal.c

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,9 @@ ruby_default_signal(int sig)
343343
raise(sig);
344344
}
345345

346+
static int signal_ignored(int sig);
347+
static void signal_enque(int sig);
348+
346349
/*
347350
* call-seq:
348351
* Process.kill(signal, pid, ...) -> fixnum
@@ -429,6 +432,8 @@ rb_f_kill(int argc, VALUE *argv)
429432
break;
430433
}
431434

435+
if (argc <= 1) return INT2FIX(0);
436+
432437
if (sig < 0) {
433438
sig = -sig;
434439
for (i=1; i<argc; i++) {
@@ -437,8 +442,42 @@ rb_f_kill(int argc, VALUE *argv)
437442
}
438443
}
439444
else {
445+
const rb_pid_t self = (GET_THREAD() == GET_VM()->main_thread) ? getpid() : -1;
446+
int wakeup = 0;
447+
440448
for (i=1; i<argc; i++) {
441-
ruby_kill(NUM2PIDT(argv[i]), sig);
449+
rb_pid_t pid = NUM2PIDT(argv[i]);
450+
451+
if ((sig != 0) && (self != -1) && (pid == self)) {
452+
/*
453+
* When target pid is self, many caller assume signal will be
454+
* delivered immediately and synchronously.
455+
*/
456+
switch (sig) {
457+
case SIGSEGV:
458+
#ifdef SIGBUS
459+
case SIGBUS:
460+
#endif
461+
#ifdef SIGKILL
462+
case SIGKILL:
463+
#endif
464+
#ifdef SIGSTOP
465+
case SIGSTOP:
466+
#endif
467+
ruby_kill(pid, sig);
468+
break;
469+
default:
470+
if (signal_ignored(sig)) break;
471+
signal_enque(sig);
472+
wakeup = 1;
473+
}
474+
}
475+
else if (kill(pid, sig) < 0) {
476+
rb_sys_fail(0);
477+
}
478+
}
479+
if (wakeup) {
480+
rb_threadptr_check_signal(GET_VM()->main_thread);
442481
}
443482
}
444483
rb_thread_execute_interrupts(rb_thread_current());
@@ -570,11 +609,32 @@ ruby_nativethread_signal(int signum, sighandler_t handler)
570609
#endif
571610
#endif
572611

573-
static RETSIGTYPE
574-
sighandler(int sig)
612+
static int
613+
signal_ignored(int sig)
614+
{
615+
#ifdef POSIX_SIGNAL
616+
struct sigaction old;
617+
(void)VALGRIND_MAKE_MEM_DEFINED(&old, sizeof(old));
618+
if (sigaction(sig, NULL, &old) < 0) return FALSE;
619+
return old.sa_handler == SIG_IGN;
620+
#else
621+
sighandler_t old = signal(sig, SIG_DFL);
622+
signal(sig, old);
623+
return old == SIG_IGN;
624+
#endif
625+
}
626+
627+
static void
628+
signal_enque(int sig)
575629
{
576630
ATOMIC_INC(signal_buff.cnt[sig]);
577631
ATOMIC_INC(signal_buff.size);
632+
}
633+
634+
static RETSIGTYPE
635+
sighandler(int sig)
636+
{
637+
signal_enque(sig);
578638
rb_thread_wakeup_timer_thread();
579639
#if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
580640
ruby_signal(sig, sighandler);

test/ruby/test_process.rb

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,6 +1192,23 @@ def test_status
11921192
end
11931193

11941194
def test_status_kill
1195+
return unless Process.respond_to?(:kill)
1196+
return unless Signal.list.include?("KILL")
1197+
1198+
# assume the system supports signal if SIGQUIT is available
1199+
expected = Signal.list.include?("QUIT") ? [false, true, false, nil] : [true, false, false, true]
1200+
1201+
with_tmpchdir do
1202+
write_file("foo", "Process.kill(:KILL, $$); exit(42)")
1203+
system(RUBY, "foo")
1204+
s = $?
1205+
assert_equal(expected,
1206+
[s.exited?, s.signaled?, s.stopped?, s.success?],
1207+
"[s.exited?, s.signaled?, s.stopped?, s.success?]")
1208+
end
1209+
end
1210+
1211+
def test_status_quit
11951212
return unless Process.respond_to?(:kill)
11961213
return unless Signal.list.include?("QUIT")
11971214

@@ -1206,16 +1223,14 @@ def test_status_kill
12061223
end
12071224
t = Time.now
12081225
s = $?
1209-
assert_equal([false, true, false],
1210-
[s.exited?, s.signaled?, s.stopped?],
1211-
"[s.exited?, s.signaled?, s.stopped?]")
1226+
assert_equal([false, true, false, nil],
1227+
[s.exited?, s.signaled?, s.stopped?, s.success?],
1228+
"[s.exited?, s.signaled?, s.stopped?, s.success?]")
12121229
assert_send(
12131230
[["#<Process::Status: pid #{ s.pid } SIGQUIT (signal #{ s.termsig })>",
12141231
"#<Process::Status: pid #{ s.pid } SIGQUIT (signal #{ s.termsig }) (core dumped)>"],
12151232
:include?,
12161233
s.inspect])
1217-
assert_equal(false, s.exited?)
1218-
assert_equal(nil, s.success?)
12191234
EnvUtil.diagnostic_reports("QUIT", RUBY, pid, t)
12201235
end
12211236
end

test/ruby/test_signal.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,4 +268,15 @@ def test_hup_me
268268
}
269269
}
270270
end if Process.respond_to?(:kill) and Signal.list.key?('HUP')
271+
272+
def test_ignored_interrupt
273+
bug9820 = '[ruby-dev:48203] [Bug #9820]'
274+
assert_separately(['-', bug9820], <<-'end;') # begin
275+
bug = ARGV.shift
276+
trap(:INT, "IGNORE")
277+
assert_nothing_raised(SignalException, bug) do
278+
Process.kill(:INT, $$)
279+
end
280+
end;
281+
end if Process.respond_to?(:kill)
271282
end

thread.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5320,23 +5320,20 @@ ruby_kill(rb_pid_t pid, int sig)
53205320
{
53215321
int err;
53225322
rb_thread_t *th = GET_THREAD();
5323-
rb_vm_t *vm = GET_VM();
53245323

53255324
/*
53265325
* When target pid is self, many caller assume signal will be
53275326
* delivered immediately and synchronously.
53285327
*/
5329-
if ((sig != 0) && (th == vm->main_thread) && (pid == getpid())) {
5328+
{
53305329
GVL_UNLOCK_BEGIN();
53315330
native_mutex_lock(&th->interrupt_lock);
53325331
err = kill(pid, sig);
53335332
native_cond_wait(&th->interrupt_cond, &th->interrupt_lock);
53345333
native_mutex_unlock(&th->interrupt_lock);
53355334
GVL_UNLOCK_END();
53365335
}
5337-
else {
5338-
err = kill(pid, sig);
5339-
}
5340-
if (err < 0)
5336+
if (err < 0) {
53415337
rb_sys_fail(0);
5338+
}
53425339
}

version.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#define RUBY_VERSION "2.1.2"
2-
#define RUBY_RELEASE_DATE "2014-08-31"
3-
#define RUBY_PATCHLEVEL 216
2+
#define RUBY_RELEASE_DATE "2014-09-02"
3+
#define RUBY_PATCHLEVEL 217
44

55
#define RUBY_RELEASE_YEAR 2014
6-
#define RUBY_RELEASE_MONTH 8
7-
#define RUBY_RELEASE_DAY 31
6+
#define RUBY_RELEASE_MONTH 9
7+
#define RUBY_RELEASE_DAY 2
88

99
#include "ruby/version.h"
1010

0 commit comments

Comments
 (0)