我正在寻找Ruby中POSIX alarm(2)
(或类似)的可移植接口。也就是说,我希望能够设置后台计时器,以便在 n 秒后向当前进程发送信号。
我在2006年的ruby-talk列表中找到了一些good discussion,它使用dl/import
提供了一个解决方案,但这有点像黑客攻击(尽管是一个整洁的黑客)并且不是很便携。< / p>
我看过备受诟病的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
调用中的进程阻塞似乎仅在(a)计时器到期和(b)用户输入新行之后抛出Timeout::Error
。并且该例外不会获得救助。 HMM。
所以我提出了这个解决方法:
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返回预期的“未处理异常”错误。
答案 0 :(得分:3)
很抱歉我没有回答你在X秒后向进程发送信号这个更大的问题,但似乎所有你想做的就是在等待输入X秒后超时,并且如果是这样,那么我会说你正在寻找Kernel.select:D
我个人从来没有用过这个,但在谷歌做了“非阻塞获取”,然后探索链接后,我发现这两个是非常宝贵的讨论:
http://www.ruby-forum.com/topic/126795(讨论多线程获取)
http://www.ruby-forum.com/topic/121404(第二篇文章中对Kernel.select的解释)
以下是如何使用它的示例。这将打印出您的提示并等待输入...如果五秒后没有输入,则程序将结束。如果有输入,只要有输入就会将其吐出并结束......显然,您可以根据自己的需要对其进行修改。
def prompt
STDOUT.write "> "
STDOUT.flush
end
def amusing_messages
[ "You must enter something!",
"Why did you even start me if you just wanted to stare at me?",
"Isn't there anything better you could be doing?",
"Just terminate me already... this is getting old",
"I'm waiting..."]
end
prompt
loop do
read_array, write_array, error_array = Kernel.select [STDIN], nil, nil, 5
if read_array.nil?
puts amusing_messages[rand(amusing_messages.length)]
else
puts "Result is: #{read_array[0].read_nonblock(30)}"
end
prompt
end
它可能没有您想要的那么优雅,但它绝对可以完成工作,而不会破坏线程。不幸的是,如果你想要更强大的东西(定时器/向过程发送信号),这对你没有帮助,遗憾的是,我不知道这是否适用于JRuby。很想知道它是否确实如此:)