summaryrefslogtreecommitdiff
path: root/lib/timeout.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/timeout.rb')
-rw-r--r--lib/timeout.rb28
1 files changed, 25 insertions, 3 deletions
diff --git a/lib/timeout.rb b/lib/timeout.rb
index 6aa938cdcf..9969fa2e57 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -123,7 +123,7 @@ module Timeout
# In that case, just return and let the main thread create the Timeout thread.
return if @timeout_thread_mutex.owned?
- @timeout_thread_mutex.synchronize do
+ Sync.synchronize @timeout_thread_mutex do
unless @timeout_thread&.alive?
@timeout_thread = create_timeout_thread
end
@@ -132,7 +132,7 @@ module Timeout
end
def add_request(request)
- @queue_mutex.synchronize do
+ Sync.synchronize @queue_mutex do
@queue << request
@condvar.signal
end
@@ -153,6 +153,7 @@ module Timeout
@done = false # protected by @mutex
end
+ # Only called by the timeout thread, so does not need Sync.synchronize
def done?
@mutex.synchronize do
@done
@@ -163,6 +164,7 @@ module Timeout
now >= @deadline
end
+ # Only called by the timeout thread, so does not need Sync.synchronize
def interrupt
@mutex.synchronize do
unless @done
@@ -173,13 +175,33 @@ module Timeout
end
def finished
- @mutex.synchronize do
+ Sync.synchronize @mutex do
@done = true
end
end
end
private_constant :Request
+ module Sync
+ # Calls mutex.synchronize(&block) but if that fails on CRuby due to being in a trap handler,
+ # run mutex.synchronize(&block) in a separate Thread instead.
+ def self.synchronize(mutex, &block)
+ begin
+ mutex.synchronize(&block)
+ rescue ThreadError => e
+ raise e unless e.message == "can't be called from trap context"
+ # Workaround CRuby issue https://bugs.ruby-lang.org/issues/19473
+ # which raises on Mutex#synchronize in trap handler.
+ # It's expensive to create a Thread just for this,
+ # but better than failing.
+ Thread.new {
+ mutex.synchronize(&block)
+ }.join
+ end
+ end
+ end
+ private_constant :Sync
+
# :startdoc:
# Perform an operation in a block, raising an exception if it takes longer than