summaryrefslogtreecommitdiff
path: root/lib/timeout.rb
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2022-05-15 13:43:29 +0200
committergit <svn-admin@ruby-lang.org>2022-05-19 07:19:40 +0900
commit354cd6f210c966327b1adffc0b81990827b77a0d (patch)
tree965dd10f1573c5c9db2dabdceed1fc0627da0c30 /lib/timeout.rb
parent89fbec224d8e1fa35e82bf2712c5a5fd3dc06b83 (diff)
[ruby/timeout] Handle Timeout + fork and add test for it
https://github.com/ruby/timeout/commit/4baee63b9b
Diffstat (limited to 'lib/timeout.rb')
-rw-r--r--lib/timeout.rb51
1 files changed, 29 insertions, 22 deletions
diff --git a/lib/timeout.rb b/lib/timeout.rb
index 3c3cb8e066..414983088c 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -95,30 +95,37 @@ module Timeout
end
private_constant :Request
+ def self.create_timeout_thread
+ Thread.new do
+ requests = []
+ while true
+ until QUEUE.empty? and !requests.empty? # wait to have at least one request
+ req = QUEUE.pop
+ requests << req unless req.done?
+ end
+ closest_deadline = requests.min_by(&:deadline).deadline
+
+ now = 0.0
+ QUEUE_MUTEX.synchronize do
+ while (now = Process.clock_gettime(Process::CLOCK_MONOTONIC)) < closest_deadline and QUEUE.empty?
+ CONDVAR.wait(QUEUE_MUTEX, closest_deadline - now)
+ end
+ end
+
+ requests.each do |req|
+ req.interrupt if req.expired?(now)
+ end
+ requests.reject!(&:done?)
+ end
+ end
+ end
+ private_class_method :create_timeout_thread
+
def self.ensure_timeout_thread_created
- unless @timeout_thread
+ unless @timeout_thread and @timeout_thread.alive?
TIMEOUT_THREAD_MUTEX.synchronize do
- @timeout_thread ||= Thread.new do
- requests = []
- while true
- until QUEUE.empty? and !requests.empty? # wait to have at least one request
- req = QUEUE.pop
- requests << req unless req.done?
- end
- closest_deadline = requests.min_by(&:deadline).deadline
-
- now = 0.0
- QUEUE_MUTEX.synchronize do
- while (now = Process.clock_gettime(Process::CLOCK_MONOTONIC)) < closest_deadline and QUEUE.empty?
- CONDVAR.wait(QUEUE_MUTEX, closest_deadline - now)
- end
- end
-
- requests.each do |req|
- req.interrupt if req.expired?(now)
- end
- requests.reject!(&:done?)
- end
+ unless @timeout_thread and @timeout_thread.alive?
+ @timeout_thread = create_timeout_thread
end
end
end