# File lib/activeldap/timeout.rb, line 14 def Timeout.alarm(sec, exception=Timeout::Error, &block) return block.call if sec == nil or sec.zero? # Trap an alarm in case it comes before we're ready orig_alrm = trap(:ALRM, 'IGNORE') # Setup a fallback in case of a race condition of an # alarm before we set the other trap trap(:ALRM) do # Don't leave zombies Process.wait2() # Restore the original handler trap('ALRM', orig_alrm) # Now raise an exception! raise exception, 'execution expired' end # Spawn the sleeper pid = Process.fork { begin # Sleep x seconds then send SIGALRM sleep(sec) # Send alarm! Process.kill(:ALRM, Process.ppid) end exit! 0 } # Setup the real handler trap(:ALRM) do # Make sure we clean up any zombies Process.waitpid(pid) # Restore the original handler trap(:ALRM, orig_alrm) # Now raise an exception! raise exception, 'execution expired' end begin # Run the code! return block.call ensure # Restore old alarm handler since we're done trap(:ALRM, orig_alrm) # Make sure the process is dead # This may be run twice (trap occurs during execution) so ignore ESRCH Process.kill(:TERM, pid) rescue Errno::ESRCH # Don't leave zombies Process.waitpid(pid) rescue Errno::ECHILD end end