-
Notifications
You must be signed in to change notification settings - Fork 25
Closed
Description
Moving the Thread to ThreadGroup::Default causes issues with enclosed ThreadGroups. (this change happend in commit c4f1385)
It goes wrong in for example the airbrake-ruby gem. (airbrake/airbrake-ruby#713 (comment))
- The airbrake-ruby notifier creates a ThreadGroup with workers.
- It encloses this group.
- A worker starts a Net::Http request. This request creates the timeout.
- The timeout thread is created in the enclosed worker ThreadGroup
- An attempt is made to move the Thread to ThreadGroup::Default
- Which results in the following exception:
#<Thread:0x0000000107da1e40 /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/gems/3.2.0/gems/airbrake-ruby-6.2.0/lib/airbrake-ruby/thread_pool.rb:131 run> terminated with exception (report_on_exception is true):
/Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/timeout.rb:123:in `add': can't move from the enclosed thread group (ThreadError)
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/timeout.rb:123:in `create_timeout_thread'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/timeout.rb:134:in `block in ensure_timeout_thread_created'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/timeout.rb:132:in `synchronize'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/timeout.rb:132:in `ensure_timeout_thread_created'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/timeout.rb:181:in `timeout'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/net/http.rb:1269:in `connect'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/net/http.rb:1248:in `do_start'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/net/http.rb:1237:in `start'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/3.2.0/net/http.rb:1817:in `request'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/gems/3.2.0/gems/airbrake-13.0.3/lib/airbrake/rails/net_http.rb:11:in `block in request'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/gems/3.2.0/gems/airbrake-13.0.3/lib/airbrake/rack.rb:21:in `capture_timing'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/gems/3.2.0/gems/airbrake-13.0.3/lib/airbrake/rails/net_http.rb:10:in `request'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/gems/3.2.0/gems/airbrake-ruby-6.2.0/lib/airbrake-ruby/sync_sender.rb:49:in `send'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/gems/3.2.0/gems/airbrake-ruby-6.2.0/lib/airbrake-ruby/async_sender.rb:51:in `block in thread_pool'
from /Users/rick/.asdf/installs/ruby/3.2.0/lib/ruby/gems/3.2.0/gems/airbrake-ruby-6.2.0/lib/airbrake-ruby/thread_pool.rb:135:in `block in spawn_worker'
This problem could be solved by making lib/timeout.rb:123
conditional
ThreadGroup::Default.add(watcher) unless watcher.group.enclosed?
Example to illustrate this behavior:
# This sample fails!
t1 = Thread.new {
sleep(2)
t2 = Thread.new { }
puts "t2.group: #{t2.group}"
ThreadGroup::Default.add(t2)
puts "Success!"
}
group = ThreadGroup.new
group.add(t1)
group.enclose
puts "t1.group: #{t1.group}"
t1.join
# This sample succeeds by adding the conditional
t1 = Thread.new {
sleep(2)
t2 = Thread.new { }
puts "t2.group: #{t2.group}"
ThreadGroup::Default.add(t2) unless t2.group.enclosed?
puts "Success!"
}
group = ThreadGroup.new
group.add(t1)
group.enclose
puts "t1.group: #{t1.group}"
t1.join
Metadata
Metadata
Assignees
Labels
No labels