首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >异步报警信号

异步报警信号
EN

Stack Overflow用户
提问于 2019-06-04 01:00:40
回答 1查看 0关注 0票数 0

我正在寻找alarm(2)Ruby中POSIX (或类似)的可移植接口。也就是说,我希望能够设置后台计时器,在n秒后向当前进程发送信号。

我在2006年的ruby-talk列表中找到了一些很好的讨论,它提供了一个使用的解决方案dl/import,但这有点像黑客(尽管是一个整洁的黑客)并且不是很便携。

我看过备受诟病的Timeout模块,虽然它与传统的解释器一起使用,但它不会在JRuby下删除它。我的程序是一个使用Readline库的小命令行shell:

代码语言:javascript
复制
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)用户输入新行之后抛出。并且该例外不会获得救助。嗯。

所以我提出了这个解决方法:

代码语言:javascript
复制
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吃信号吗?例:

代码语言:javascript
复制
SIG = 'USR2'
Signal.trap(SIG) { raise }
Process.kill(SIG, Process.pid)

JRuby只返回,Ruby返回预期的“未处理异常”错误。

EN

回答 1

Stack Overflow用户

发布于 2019-06-04 10:34:06

对不起,我没有回答你在X秒后向进程发送信号这个更大的问题,但似乎所有你想做的就是在等待输入X秒后超时,如果这是然后我会说你正在寻找Kernel.select:D

我个人从来没有使用过这个,但在谷歌做了“非阻塞获取”,并随后探索链接后,我发现这两个是非常宝贵的讨论:

http://www.ruby-forum.com/topic/126795(讨论多线程获取)

http://www.ruby-forum.com/topic/121404(第二篇文章中Kernel.select的说明)

这是一个如何使用它的示例。这将打印出您的提示并等待输入...如果五秒后没有输入,则程序将结束。如果有输入,只要有输入就会将其吐出并结束...显然,您可以根据自己的需要对其进行修改。

代码语言:javascript
复制
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。很想知道它是否确实:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100009071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档