【发布时间】:2009-02-02 08:13:55
【问题描述】:
我正在寻找 Ruby 中 POSIX alarm(2)(或类似)的可移植接口。也就是说,我希望能够设置一个后台计时器,以便在 n 秒后向当前进程发送信号。
我在 ruby-talk 列表中找到了一些 2006 年的 good discussion,它提供了使用 dl/import 的解决方案,但这有点像 hack(尽管是一个简洁的 hack)并且不是很便携。
我查看了饱受诟病的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 返回预期的“未处理异常”错误。
【问题讨论】: