Executes the method’s block. If the block execution terminates before
sec seconds has passed, it returns the result value of the block.
If not, it terminates the execution and raises exception (which
defaults to Timeout::Error).
Note that this is both a method of module Timeout, so you can ‘include Timeout’ into your classes so they have a #timeout method, as well as a module
method, so you can call it directly as Timeout.timeout().
# File lib/timeout.rb, line 43
def timeout(sec, klass = nil) #:yield: +sec+
return yield(sec) if sec == nil or sec.zero?
exception = klass || Class.new(ExitException)
begin
x = Thread.current
y = Thread.start {
begin
sleep sec
rescue => e
x.raise e
else
x.raise exception, "execution expired" if x.alive?
end
}
return yield(sec)
rescue exception => e
rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/
(bt = e.backtrace).reject! {|m| rej =~ m}
level = -caller(CALLER_OFFSET).size
while THIS_FILE =~ bt[level]
bt.delete_at(level)
level += 1
end
raise if klass # if exception class is specified, it
# would be expected outside.
raise Error, e.message, e.backtrace
ensure
if y and y.alive?
y.kill
y.join # make sure y is dead.
end
end
end