Module: Timeout
- Defined in:
- lib/timeout.rb
Overview
timeout.rb
execution timeout
Synopsis
require 'timeout'
status = Timeout::timeout(5) {
# Something that should be interrupted if it takes too much time...
}
Description
A way of performing a potentially long-running operation in a thread, and terminating it's execution if it hasn't finished by a fixed amount of time.
Previous versions of timeout didn't provide use a module for namespace. This version provides both Timeout.timeout, and a backwards-compatible #timeout.
Copyright
Copyright |
(C) 2000 Network Applied Communication Laboratory, Inc. |
Copyright |
(C) 2000 Information-technology Promotion Agency, Japan |
Defined Under Namespace
Classes: Error, ExitException
Constant Summary
- THIS_FILE =
/\A#{Regexp.quote(__FILE__)}:/o- CALLER_OFFSET =
((c = caller[0]) && THIS_FILE =~ c) ? 1 : 0
Instance Method Summary (collapse)
-
- (Object) timeout(sec, klass = nil)
Executes the method's block.
Instance Method Details
- (Object) timeout(sec, klass = nil)
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().
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# 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 begin x = Thread.current y = Thread.start { begin sleep sec rescue => e x.raise e else x.raise exception, "execution expired" end } return yield(sec) ensure if y y.kill y.join # make sure y is dead. end end rescue exception => e rej = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-4}\z/o (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., e.backtrace end end |