diff options
author | Andrew Haines <andrew@haines.org.nz> | 2021-07-15 11:36:46 +0100 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2021-07-27 09:25:55 +0900 |
commit | 705b1bdef2caf1bee052384b3c62c201f4fa5479 (patch) | |
tree | 49528530f5ffaa4a3d354aed7f3a5acd808ba353 /lib/bundler/worker.rb | |
parent | c8172d0b96aa91b421e77ca0bedc3f12ad8c5fdc (diff) |
[rubygems/rubygems] Fix interrupt handling in Bundler workers
The existing interrupt handling using `SharedHelpers.trap` fails when the previous
handler for a signal is not callable (for example, when it is the string "DEFAULT").
Instead, we now handle interrupts by aborting the process when worker threads are
running, and restore the previous handler after worker threads are finished.
Fixes #4764.
https://github.com/rubygems/rubygems/commit/b9f455d487
Diffstat (limited to 'lib/bundler/worker.rb')
-rw-r--r-- | lib/bundler/worker.rb | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/lib/bundler/worker.rb b/lib/bundler/worker.rb index 0380096523..5e4ee21c51 100644 --- a/lib/bundler/worker.rb +++ b/lib/bundler/worker.rb @@ -26,7 +26,7 @@ module Bundler @func = func @size = size @threads = nil - SharedHelpers.trap("INT") { abort_threads } + @previous_interrupt_handler = nil end # Enqueue a request to be executed in the worker pool @@ -68,13 +68,16 @@ module Bundler # so as worker threads after retrieving it, shut themselves down def stop_threads return unless @threads + @threads.each { @request_queue.enq POISON } @threads.each(&:join) + + remove_interrupt_handler + @threads = nil end def abort_threads - return unless @threads Bundler.ui.debug("\n#{caller.join("\n")}") @threads.each(&:exit) exit 1 @@ -94,11 +97,23 @@ module Bundler end end.compact + add_interrupt_handler unless @threads.empty? + return if creation_errors.empty? message = "Failed to create threads for the #{name} worker: #{creation_errors.map(&:to_s).uniq.join(", ")}" raise ThreadCreationError, message if @threads.empty? Bundler.ui.info message end + + def add_interrupt_handler + @previous_interrupt_handler = trap("INT") { abort_threads } + end + + def remove_interrupt_handler + return unless @previous_interrupt_handler + + trap "INT", @previous_interrupt_handler + end end end |