1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* vm_core.h (enum rb_thread_status): remove THREAD_TO_KILL

* vm_core.h (struct rb_thread_struct): add to_kill field
* thread.c (terminate_i): convert THREAD_TO_KILL to to_kill.
* thread.c (rb_threadptr_to_kill): ditto.
* thread.c (rb_thread_kill): ditto.
* thread.c (rb_thread_wakeup_alive): ditto.
* thread.c (thread_list_i): ditto.
* thread.c (static const char): ditto.
* thread.c (thread_status_name): ditto.
* thread.c (rb_thread_status): ditto.
* thread.c (rb_thread_inspect): ditto.
* vm_backtrace.c (thread_backtrace_to_ary): ditto.

* thread.c (rb_threadptr_execute_interrupts): fix thread status
  overwritten issue. [Bug #7450] [ruby-core:50249]

* test/ruby/test_thread.rb (test_hread_status_raise_after_kill):
  test for the above.
* test/ruby/test_thread.rb (test_thread_status_in_trap): test for
  thread status in trap.
* test/ruby/test_thread.rb (test_status_and_stop_p): remove
  Thread.control_interrupt unsafe test. Thread#kill no longer
  changes thread status. Instead of, Thread#kill receiver changes
  their own status when receiving kill signal.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37931 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
kosaki 2012-11-28 08:31:03 +00:00
parent b8a1e36201
commit 9cbf473287
5 changed files with 93 additions and 35 deletions

View file

@ -1,3 +1,30 @@
Wed Nov 28 16:40:14 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* vm_core.h (enum rb_thread_status): remove THREAD_TO_KILL
* vm_core.h (struct rb_thread_struct): add to_kill field
* thread.c (terminate_i): convert THREAD_TO_KILL to to_kill.
* thread.c (rb_threadptr_to_kill): ditto.
* thread.c (rb_thread_kill): ditto.
* thread.c (rb_thread_wakeup_alive): ditto.
* thread.c (thread_list_i): ditto.
* thread.c (static const char): ditto.
* thread.c (thread_status_name): ditto.
* thread.c (rb_thread_status): ditto.
* thread.c (rb_thread_inspect): ditto.
* vm_backtrace.c (thread_backtrace_to_ary): ditto.
* thread.c (rb_threadptr_execute_interrupts): fix thread status
overwritten issue. [Bug #7450] [ruby-core:50249]
* test/ruby/test_thread.rb (test_hread_status_raise_after_kill):
test for the above.
* test/ruby/test_thread.rb (test_thread_status_in_trap): test for
thread status in trap.
* test/ruby/test_thread.rb (test_status_and_stop_p): remove
Thread.control_interrupt unsafe test. Thread#kill no longer
changes thread status. Instead of, Thread#kill receiver changes
their own status when receiving kill signal.
Wed Nov 28 16:21:46 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* thread.c (struct rb_mutex_struct): add allow_trap field.

View file

@ -497,7 +497,6 @@ class TestThread < Test::Unit::TestCase
a = ::Thread.new { raise("die now") }
b = Thread.new { Thread.stop }
c = Thread.new { Thread.exit }
d = Thread.new { sleep }
e = Thread.current
sleep 0.5
@ -511,21 +510,14 @@ class TestThread < Test::Unit::TestCase
assert_match(/^#<TestThread::Thread:.* dead>$/, c.inspect)
assert(c.stop?)
d.kill
# to avoid thread switching...
ds1 = d.status
ds2 = d.stop?
es1 = e.status
es2 = e.stop?
assert_equal(["aborting", false], [ds1, ds2])
assert_equal(["run", false], [es1, es2])
ensure
a.kill if a
b.kill if b
c.kill if c
d.kill if d
end
def test_safe_level
@ -912,4 +904,47 @@ Thread.new(Thread.current) {|mth|
}
INPUT
end
def test_thread_status_in_trap
# when running trap handler, Thread#status must show "run"
# Even though interrupted from sleeping function
assert_in_out_err([], <<-INPUT, %w(sleep run), [])
Signal.trap(:INT) {
puts Thread.current.status
}
Thread.new(Thread.current) {|mth|
sleep 0.01
puts mth.status
Process.kill(:INT, $$)
}
sleep 0.1
INPUT
end
# Bug #7450
def test_thread_status_raise_after_kill
ary = []
t = Thread.new {
begin
ary << Thread.current.status
sleep
ensure
begin
ary << Thread.current.status
sleep
ensure
ary << Thread.current.status
end
end
}
sleep 0.01
t.kill
sleep 0.01
t.raise
sleep 0.01
assert_equal(ary, ["run", "aborting", "aborting"])
end
end

View file

@ -326,7 +326,6 @@ terminate_i(st_data_t key, st_data_t val, rb_thread_t *main_thread)
if (th != main_thread) {
thread_debug("terminate_i: %p\n", (void *)th);
rb_threadptr_async_errinfo_enque(th, eTerminateSignal);
th->status = THREAD_TO_KILL;
rb_threadptr_interrupt(th);
}
else {
@ -1732,7 +1731,8 @@ static void
rb_threadptr_to_kill(rb_thread_t *th)
{
rb_threadptr_async_errinfo_clear(th);
th->status = THREAD_TO_KILL;
th->status = THREAD_RUNNABLE;
th->to_kill = 1;
th->errinfo = INT2FIX(TAG_FATAL);
TH_JUMP_TAG(th, TAG_FATAL);
}
@ -1743,7 +1743,6 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
if (th->raised_flag) return;
while (1) {
enum rb_thread_status status = th->status;
rb_atomic_t interrupt;
rb_atomic_t old;
int sig;
@ -1766,13 +1765,16 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
finalizer_interrupt = interrupt & FINALIZER_INTERRUPT_MASK;
trap_interrupt = interrupt & TRAP_INTERRUPT_MASK;
th->status = THREAD_RUNNABLE;
/* signal handling */
if (trap_interrupt && (th == th->vm->main_thread)) {
enum rb_thread_status prev_status = th->status;
th->status = THREAD_RUNNABLE;
while ((sig = rb_get_next_signal()) != 0) {
rb_signal_exec(th, sig);
}
th->status = prev_status;
}
/* exception from another thread */
@ -1788,10 +1790,13 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
rb_threadptr_to_kill(th);
}
else {
/* set runnable if th was slept. */
if (th->status == THREAD_STOPPED ||
th->status == THREAD_STOPPED_FOREVER)
th->status = THREAD_RUNNABLE;
rb_exc_raise(err);
}
}
th->status = status;
if (finalizer_interrupt) {
rb_gc_finalize_deferred();
@ -1805,7 +1810,7 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
else
limits_us >>= -th->priority;
if (status == THREAD_RUNNABLE || status == THREAD_TO_KILL)
if (th->status == THREAD_RUNNABLE)
th->running_time_us += TIME_QUANTUM_USEC;
EXEC_EVENT_HOOK(th, RUBY_EVENT_SWITCH, th->cfp->self, 0, 0, Qundef);
@ -1985,7 +1990,7 @@ rb_thread_kill(VALUE thread)
if (th != GET_THREAD() && th->safe_level < 4) {
rb_secure(4);
}
if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED) {
if (th->to_kill || th->status == THREAD_KILLED) {
return thread;
}
if (th == th->vm->main_thread) {
@ -2000,7 +2005,6 @@ rb_thread_kill(VALUE thread)
}
else {
rb_threadptr_async_errinfo_enque(th, eKillSignal);
th->status = THREAD_TO_KILL;
rb_threadptr_interrupt(th);
}
return thread;
@ -2082,9 +2086,8 @@ rb_thread_wakeup_alive(VALUE thread)
return Qnil;
}
rb_threadptr_ready(th);
if (th->status != THREAD_TO_KILL) {
if (th->status == THREAD_STOPPED || th->status == THREAD_STOPPED_FOREVER)
th->status = THREAD_RUNNABLE;
}
return thread;
}
@ -2157,7 +2160,6 @@ thread_list_i(st_data_t key, st_data_t val, void *data)
case THREAD_RUNNABLE:
case THREAD_STOPPED:
case THREAD_STOPPED_FOREVER:
case THREAD_TO_KILL:
rb_ary_push(ary, th->self);
default:
break;
@ -2352,16 +2354,17 @@ rb_thread_group(VALUE thread)
}
static const char *
thread_status_name(enum rb_thread_status status)
thread_status_name(rb_thread_t *th)
{
switch (status) {
switch (th->status) {
case THREAD_RUNNABLE:
return "run";
if (th->to_kill)
return "aborting";
else
return "run";
case THREAD_STOPPED:
case THREAD_STOPPED_FOREVER:
return "sleep";
case THREAD_TO_KILL:
return "aborting";
case THREAD_KILLED:
return "dead";
default:
@ -2411,7 +2414,7 @@ rb_thread_status(VALUE thread)
}
return Qfalse;
}
return rb_str_new2(thread_status_name(th->status));
return rb_str_new2(thread_status_name(th));
}
@ -2500,7 +2503,7 @@ rb_thread_inspect(VALUE thread)
VALUE str;
GetThreadPtr(thread, th);
status = thread_status_name(th->status);
status = thread_status_name(th);
str = rb_sprintf("#<%s:%p %s>", cname, (void *)thread, status);
OBJ_INFECT(str, thread);

View file

@ -738,15 +738,8 @@ thread_backtrace_to_ary(int argc, VALUE *argv, VALUE thval, int to_str)
rb_thread_t *th;
GetThreadPtr(thval, th);
switch (th->status) {
case THREAD_RUNNABLE:
case THREAD_STOPPED:
case THREAD_STOPPED_FOREVER:
break;
case THREAD_TO_KILL:
case THREAD_KILLED:
if (th->to_kill || th->status == THREAD_KILLED)
return Qnil;
}
return vm_backtrace_to_ary(th, argc, argv, 0, 0, to_str);
}

View file

@ -425,7 +425,6 @@ extern const rb_data_type_t ruby_threadptr_data_type;
TypedData_Get_Struct((obj), rb_thread_t, &ruby_threadptr_data_type, (ptr))
enum rb_thread_status {
THREAD_TO_KILL,
THREAD_RUNNABLE,
THREAD_STOPPED,
THREAD_STOPPED_FOREVER,
@ -498,6 +497,7 @@ typedef struct rb_thread_struct {
/* thread control */
rb_thread_id_t thread_id;
enum rb_thread_status status;
int to_kill;
int priority;
native_thread_data_t native_thread_data;