我正在寻找alarm(2)
Ruby 中 POSIX(或类似)的可移植接口。也就是说,我希望能够设置一个后台计时器,在n秒后向当前进程发送信号。
我从 2006 年的 ruby-talk 列表中找到了一些很好的讨论,该列表提供了一个使用dl/import
.
我已经查看了这个备受诟病的Timeout
模块,尽管它在传统解释器中运行良好,但它不会在 JRuby 下削减它。我的程序是一个使用 Readline 库的小型命令行 shell:
TIMEOUT = 5 # seconds
loop do
input = nil
begin
Timeout.timeout(TIMEOUT) do
input = Readline::readline('> ', nil)
end
rescue Timeout::Error
puts "Timeout"
next
end
# do something with input
end
在 JRuby 下,似乎进程阻塞在readline
调用中,并且Timeout::Error
仅在 (a) 计时器到期和 (b) 用户输入新行之后才被抛出。并且异常没有得到拯救。唔。
所以我想出了这个解决方法:
require 'readline'
class TimeoutException < Exception ; end
TIMEOUT = 5 # seconds
loop do
input = nil
start_time = Time.now
thread = Thread.new { input = Readline::readline('> ', nil) }
begin
while thread.alive? do
sleep(1) # prevent CPU from melting
raise TimeoutException if(Time.now - start_time > TIMEOUT)
end
rescue TimeoutException
thread.exit
puts "Timeout"
end
# do something with input
end
这是...笨重(让我们有礼貌)。我只是想要alarm(2)
!我真的不想为此拖入非核心库(例如终结者)。有没有更好的办法?
编辑:我无法获得另一种选择——创建一个睡眠然后向进程发送信号的线程——在 JRuby 下工作。JRuby 吃信号吗?例子:
SIG = 'USR2'
Signal.trap(SIG) { raise }
Process.kill(SIG, Process.pid)
JRuby 简单地返回,Ruby 返回预期的“未处理异常”错误。