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

Set Thread.report_on_exception=true by default to report exceptions in Threads

* [Feature #14143] [ruby-core:83979]
* vm.c (vm_init2): Set Thread.report_on_exception to true.
* thread.c (thread_start_func_2): Add indication the message is caused
  by report_on_exception = true.
* spec/ruby: Specify the new behavior.
* test/ruby/test_thread.rb: Adapt and improve tests for
  Thread.report_on_exception and Thread#report_on_exception.
* test/ruby/test_thread.rb, test/ruby/test_exception.rb: Unset
  report_on_exception for tests expecting no extra output.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61183 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2017-12-12 18:43:42 +00:00
parent 2406207cbb
commit 5a3c024df0
5 changed files with 42 additions and 17 deletions

View file

@ -2,11 +2,19 @@ require File.expand_path('../../../spec_helper', __FILE__)
ruby_version_is "2.4" do
describe "Thread.report_on_exception" do
ruby_version_is "2.4"..."2.5" do
it "defaults to false" do
ruby_exe("p Thread.report_on_exception").should == "false\n"
end
end
ruby_version_is "2.5" do
it "defaults to true" do
ruby_exe("p Thread.report_on_exception").should == "true\n"
end
end
end
describe "Thread.report_on_exception=" do
before :each do
@report_on_exception = Thread.report_on_exception

View file

@ -354,6 +354,7 @@ class TestException < Test::Unit::TestCase
def test_thread_signal_location
_, stderr, _ = EnvUtil.invoke_ruby(%w"--disable-gems -d", <<-RUBY, false, true)
Thread.start do
Thread.current.report_on_exception = false
begin
Process.kill(:INT, $$)
ensure

View file

@ -317,7 +317,10 @@ class TestThread < Test::Unit::TestCase
assert_in_out_err([], <<-INPUT, %w(false 1), [])
p Thread.abort_on_exception
begin
t = Thread.new { raise }
t = Thread.new {
Thread.current.report_on_exception = false
raise
}
Thread.pass until t.stop?
p 1
rescue
@ -329,7 +332,10 @@ class TestThread < Test::Unit::TestCase
Thread.abort_on_exception = true
p Thread.abort_on_exception
begin
Thread.new { raise }
Thread.new {
Thread.current.report_on_exception = false
raise
}
sleep 0.5
p 1
rescue
@ -352,7 +358,11 @@ class TestThread < Test::Unit::TestCase
p Thread.abort_on_exception
begin
ok = false
t = Thread.new { Thread.pass until ok; raise }
t = Thread.new {
Thread.current.report_on_exception = false
Thread.pass until ok
raise
}
t.abort_on_exception = true
p t.abort_on_exception
ok = 1
@ -370,17 +380,20 @@ class TestThread < Test::Unit::TestCase
q1 = Thread::Queue.new
q2 = Thread::Queue.new
assert_equal(false, Thread.report_on_exception,
"global flags is false by default")
assert_equal(false, Thread.current.report_on_exception)
assert_equal(true, Thread.report_on_exception,
"global flag is true by default")
assert_equal(false, Thread.current.report_on_exception,
"the main thread has report_on_exception=false")
Thread.current.report_on_exception = true
assert_equal(false,
Thread.report_on_exception = true
Thread.current.report_on_exception = false
assert_equal(true,
Thread.start {Thread.current.report_on_exception}.value,
"should not inherit from the parent thread")
"should not inherit from the parent thread but from the global flag")
assert_warn("", "exception should be ignored silently") {
assert_warn("", "exception should be ignored silently when false") {
th = Thread.start {
Thread.current.report_on_exception = false
q1.push(Thread.current.report_on_exception)
raise "report 1"
}
@ -388,7 +401,7 @@ class TestThread < Test::Unit::TestCase
Thread.pass while th.alive?
}
assert_warn(/report 2/, "exception should be reported") {
assert_warn(/report 2/, "exception should be reported when true") {
th = Thread.start {
q1.push(Thread.current.report_on_exception = true)
raise "report 2"
@ -397,8 +410,8 @@ class TestThread < Test::Unit::TestCase
Thread.pass while th.alive?
}
assert_equal(false, Thread.report_on_exception)
assert_warn("", "the global flag should not affect already started threads") {
Thread.report_on_exception = false
th = Thread.start {
q2.pop
q1.push(Thread.current.report_on_exception)
@ -409,8 +422,8 @@ class TestThread < Test::Unit::TestCase
Thread.pass while th.alive?
}
assert_equal(true, Thread.report_on_exception)
assert_warn(/report 4/, "should defaults to the global flag at the start") {
Thread.report_on_exception = true
th = Thread.start {
q1.push(Thread.current.report_on_exception)
raise "report 4"
@ -419,7 +432,7 @@ class TestThread < Test::Unit::TestCase
Thread.pass while th.alive?
}
assert_warn(/report 5/, "should defaults to the global flag at the start") {
assert_warn(/report 5/, "should first report and then raise with report_on_exception + abort_on_exception") {
th = Thread.start {
Thread.current.report_on_exception = true
Thread.current.abort_on_exception = true
@ -780,6 +793,7 @@ class TestThread < Test::Unit::TestCase
th_waiting = true
t = Thread.new {
Thread.current.report_on_exception = false
Thread.handle_interrupt(RuntimeError => :on_blocking) {
nil while th_waiting
# async interrupt should be raised _before_ writing puts arguments
@ -800,6 +814,7 @@ class TestThread < Test::Unit::TestCase
th_waiting = false
t = Thread.new {
Thread.current.report_on_exception = false
Thread.handle_interrupt(RuntimeError => :on_blocking) {
th_waiting = true
nil while th_waiting

View file

@ -648,7 +648,7 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s
else {
if (th->report_on_exception) {
VALUE mesg = rb_thread_to_s(th->self);
rb_str_cat_cstr(mesg, " terminated with exception:\n");
rb_str_cat_cstr(mesg, " terminated with exception (report_on_exception is true):\n");
rb_write_error_str(mesg);
rb_ec_error_print(th->ec, errinfo);
}

1
vm.c
View file

@ -2280,6 +2280,7 @@ vm_init2(rb_vm_t *vm)
{
MEMZERO(vm, rb_vm_t, 1);
rb_vm_living_threads_init(vm);
vm->thread_report_on_exception = 1;
vm->src_encoding_index = -1;
vm_default_params_setup(vm);