summaryrefslogtreecommitdiff
path: root/lib/bundler/worker.rb
diff options
context:
space:
mode:
authorAndrew Haines <andrew@haines.org.nz>2021-07-15 11:36:46 +0100
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2021-07-27 09:25:55 +0900
commit705b1bdef2caf1bee052384b3c62c201f4fa5479 (patch)
tree49528530f5ffaa4a3d354aed7f3a5acd808ba353 /lib/bundler/worker.rb
parentc8172d0b96aa91b421e77ca0bedc3f12ad8c5fdc (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.rb19
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