Module: Timeout
Relationships & Source Files | |
Namespace Children | |
Exceptions:
| |
Defined in: | lib/timeout.rb |
Overview
Timeout
long-running blocks
Synopsis
require 'timeout'
status = Timeout::timeout(5) {
# Something that should be interrupted if it takes more than 5 seconds...
}
Description
Timeout
provides a way to auto-terminate a potentially long-running operation if it hasn't finished in a fixed amount of time.
Previous versions didn't use a module for namespacing, however #timeout is provided for backwards compatibility. You should prefer #timeout instead.
Copyright
- Copyright
-
(C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright
-
(C) 2000 Information-technology Promotion Agency, Japan
Class Method Summary
-
.timeout(sec, klass = nil)
mod_func
Perform an operation in a block, raising an error if it takes longer than
sec
seconds to complete.
Class Method Details
.timeout(sec, klass = nil) (mod_func)
Perform an operation in a block, raising an error if it takes longer than sec
seconds to complete.
sec
-
Number of seconds to wait for the block to terminate. Any number may be used, including Floats to specify fractional seconds. A value of 0 or
nil
will execute the block without any timeout. klass
-
Exception Class to raise if the block fails to terminate in
sec
seconds. Omitting will use the default, Timeout::Error
Returns the result of the block if the block completed before sec
seconds, otherwise throws an exception, based on the value of klass
.
The exception thrown to terminate the given block cannot be rescued inside the block unless klass
is given explicitly.
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 73
def timeout(sec, klass = nil) #:yield: sec return yield(sec) if sec == nil or sec.zero? = "execution expired".freeze from = "from #{caller_locations(1, 1)[0]}" if $DEBUG e = Error bl = proc do |exception| begin x = Thread.current y = Thread.start { Thread.current.name = from begin sleep sec rescue => e x.raise e else x.raise exception, end } return yield(sec) ensure if y y.kill y.join # make sure y is dead. end end end if klass begin bl.call(klass) rescue klass => e bt = e.backtrace end else bt = Error.catch(, &bl) end level = -caller(CALLER_OFFSET).size-2 while THIS_FILE =~ bt[level] bt.delete_at(level) end raise(e, , bt) end