module Timeout
frozen_string_literal: false 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
Public Class Methods
# File lib/timeout.rb, line 73 def timeout(sec, klass = nil) #:yield: +sec+ return yield(sec) if sec == nil or sec.zero? message = "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, message 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(message, &bl) end level = -caller(CALLER_OFFSET).size-2 while THIS_FILE =~ bt[level] bt.delete_at(level) end raise(e, message, bt) end
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.
Private Instance Methods
# File lib/timeout.rb, line 73 def timeout(sec, klass = nil) #:yield: +sec+ return yield(sec) if sec == nil or sec.zero? message = "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, message 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(message, &bl) end level = -caller(CALLER_OFFSET).size-2 while THIS_FILE =~ bt[level] bt.delete_at(level) end raise(e, message, bt) end
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.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.