require 'ffi/libc' require 'timeout' module FFI module LibC attach_function :alarm, [:uint], :uint unless FFI::LibC.respond_to? :alarm end end module TimeoutInterruptSingleton class < secs Signal.trap 'ALRM', &method( :alarm_trap) FFI::LibC.alarm secs.to_i+1 end end def timeout seconds = nil, exception = nil return setup if seconds.nil? seconds = seconds.to_i exception ||= TimeoutInterrupt::Error raise exception, "Timeout must be longer than '0' seconds." unless 0 < seconds unless block_given? return lambda {|&e| raise exception, "Expect a lambda." unless e timeout seconds, exception, &e } end at = Time.now + seconds key, bt = Random.rand( 2**64-1), Kernel.caller begin self.timeouts[key] = [at, bt, exception] setup yield ensure self.timeouts.delete key setup end end end end module TimeoutInterrupt class Error < Timeout::Error end def self.timeout seconds = nil, exception = nil, &e TimeoutInterruptSingleton.timeout seconds, exception, &e end def timeout seconds = nil, exception = nil, &e TimeoutInterruptSingleton.timeout seconds, exception, &e end end