[ruby/timeout] Handle Timeout + fork and add test for it
https://github.com/ruby/timeout/commit/4baee63b9b
This commit is contained in:
parent
89fbec224d
commit
354cd6f210
@ -95,31 +95,38 @@ module Timeout
|
|||||||
end
|
end
|
||||||
private_constant :Request
|
private_constant :Request
|
||||||
|
|
||||||
def self.ensure_timeout_thread_created
|
def self.create_timeout_thread
|
||||||
unless @timeout_thread
|
Thread.new do
|
||||||
TIMEOUT_THREAD_MUTEX.synchronize do
|
requests = []
|
||||||
@timeout_thread ||= Thread.new do
|
while true
|
||||||
requests = []
|
until QUEUE.empty? and !requests.empty? # wait to have at least one request
|
||||||
while true
|
req = QUEUE.pop
|
||||||
until QUEUE.empty? and !requests.empty? # wait to have at least one request
|
requests << req unless req.done?
|
||||||
req = QUEUE.pop
|
end
|
||||||
requests << req unless req.done?
|
closest_deadline = requests.min_by(&:deadline).deadline
|
||||||
end
|
|
||||||
closest_deadline = requests.min_by(&:deadline).deadline
|
|
||||||
|
|
||||||
now = 0.0
|
now = 0.0
|
||||||
QUEUE_MUTEX.synchronize do
|
QUEUE_MUTEX.synchronize do
|
||||||
while (now = Process.clock_gettime(Process::CLOCK_MONOTONIC)) < closest_deadline and QUEUE.empty?
|
while (now = Process.clock_gettime(Process::CLOCK_MONOTONIC)) < closest_deadline and QUEUE.empty?
|
||||||
CONDVAR.wait(QUEUE_MUTEX, closest_deadline - now)
|
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
|
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 and @timeout_thread.alive?
|
||||||
|
TIMEOUT_THREAD_MUTEX.synchronize do
|
||||||
|
unless @timeout_thread and @timeout_thread.alive?
|
||||||
|
@timeout_thread = create_timeout_thread
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -139,4 +139,24 @@ class TestTimeout < Test::Unit::TestCase
|
|||||||
}
|
}
|
||||||
assert(ok, bug11344)
|
assert(ok, bug11344)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_fork
|
||||||
|
omit 'fork not supported' unless Process.respond_to?(:fork)
|
||||||
|
r, w = IO.pipe
|
||||||
|
pid = fork do
|
||||||
|
r.close
|
||||||
|
begin
|
||||||
|
r = Timeout.timeout(0.01) { sleep 5 }
|
||||||
|
w.write r.inspect
|
||||||
|
rescue Timeout::Error
|
||||||
|
w.write 'timeout'
|
||||||
|
ensure
|
||||||
|
w.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
w.close
|
||||||
|
Process.wait pid
|
||||||
|
assert_equal 'timeout', r.read
|
||||||
|
r.close
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user