开发者

interprocess signal handling in Ruby

I run this script:

t = fork do
  Signal.trap "INT" do
    puts "child"
    exit
  end

  sleep 10
end


Signal.trap "INT" do
  puts "parent"
  Process.kill "INT", t
  Process.waitpid t  
  exit
end

Process.waitpid t

When I do CTRL+C, I get

$ ruby sigtest.rb 
^Cchild 
parent

You can see that "INT" passed to every process and Process.kill "INT", t try to kill process which already died. Is there way to do so that user INT signal will be passed only to the parent? And output will be:

$ ruby sigtest.rb 
^Cparent
child

Solution

Rules:

  • W开发者_如何学编程hen you press ctrl+c, SIGINT is passed to whole process group.
  • When you fork new process, signal handlers are not passed to new process

So if you want to control child process signals manually, you have to change GID of the process.

See

  • http://corelib.rubyonrails.org/classes/Process/Sys.html#M001961
  • http://ruby.runpaint.org/processes (paragraph "Options Hash")
  def system cmd
    pid = fork do
     exec cmd, {:pgroup => true}
    end

    Process.wait pid
    $?.success?
  end

  def ` cmd # `make syntax highlight happy

    readme, writeme = IO.pipe
    pid = fork do
      $stdout.reopen writeme
      readme.close
      exec cmd, {:pgroup => true}
    end

    writeme.close
    data = readme.read

    Process.wait pid

    data
  end


You could always have the child ignore the INT signal.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜