Issue #14143 has been updated by Eregon (Benoit Daloze).


I think it is time to do this, and most rubyists using threads with Ruby seem to agree with this
(see #6647 and I can say at least JRuby & TruffleRuby implementers want this).

Other threads should write a backtrace just like the main thread when they die due to an exception,
and not hope there will be a Thread#join soon enough.
Threads are heavyweight in Ruby, they are rarely if ever used as an isolation mechanism,
and we cannot assume Thread#join will always be called.
Proper exception handling in threads should anyway not rely on Thread#join semantics
but deal with the exception and communicate the failure with other threads explicitly.

A one-liner example to illustrate:

    $ ruby -e 'q=Queue.new; t=Thread.new{ q.push "abc".starts_with?("foo") }; p q.pop; t.join'

This small example will show a deadlock message, but not what is the source of the problem:

    -e:1:in `pop': No live threads left. Deadlock? (fatal)
    1 threads, 1 sleeps current:0x00005599e5464bf0 main thread:0x00005599e512e5e0
    * #<Thread:0x00005599e5161eb0 sleep_forever>
       rb_thread_t:0x00005599e512e5e0 native:0x00007f4493ac8700 int:0
       -e:1:in `pop'
       -e:1:in `<main>'
    	from -e:1:in `<main>'


Thread.report_on_exception=true by default would clearly show the misspelled method name:

    #<Thread:0x000055bbcaf3cb00@-e:1 run> terminated with exception:
    -e:1:in `block in <main>': undefined method `starts_with?' for "abc":String (NoMethodError)
    Did you mean?  start_with?

-d/--debug is not a good fit here because:
* it changes the semantics to abort_on_exception.
* it outputs a lot of extra exceptions (in bigger programs), yet without showing the backtrace of exceptions.
* it does not differentiate between exceptions which killed a Thread and exceptions which are rescue'd.

report-on-GC as proposed in #6647 is of no use here since the Thread might be GC-reachable long after it dies,
and it adds extra non-determinism which has no place in error reporting.

----------------------------------------
Feature #14143: Thread.report_on_exception should be true by default
https://bugs.ruby-lang.org/issues/14143#change-68059

* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Extracted from #6647 to focus on the default value now that the feature is implemented.

I strongly believe we should have Thread.report_on_exception = true by default.

It only adds some extra stderr output for apps which let threads die, which is very rarely intended.
If it is intended, then one can use Thread.current.report_on_exception = false
to clarify it's OK for that thread to die and the failure is handled by the app on Thread#join.

I enabled Thread.report_on_exception=true by default in ruby/spec, see https://github.com/ruby/spec/pull/517,
the only cases needing Thread.current.report_on_exception=false
are the specs testing report_on_exception itself and Thread#join/value/status/raise.

Enabling it for test-all shows a fair amount of extra output and failures, which I would bet some of them are bugs in the tests (I already found one, r60854 & r60870),
and other tests should simply more carefully test what they expect
(for instance assert_raise() inside the Thread just around the code raising an exception and join the Thread).

I am willing to help to reduce the extra output and failures in test-all,
but I would like a OK from Matz to try enabling Thread.report_on_exception by default.

Dear Matz, do you think it is reasonable to show exceptions killing threads on stderr by default,
instead of silently swallowing them until Thread#join ?
(if there is ever a Thread#join ..., often not or too late, when the rest of the application has crashed)



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>