Ruby 中的进程间信号处理

发布于 2024-11-27 20:29:15 字数 1497 浏览 0 评论 0原文

我运行这个脚本:

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

当我执行 CTRL+C 时,我得到

$ ruby sigtest.rb 
^Cchild 
parent

You can see that "INT" was pass to every process and Process.kill "INT", t try to Kill 已经死亡的进程。有没有办法让用户 INT 信号仅传递给父级?输出将是:

$ ruby sigtest.rb 
^Cparent
child

解决方案

规则:

  • 当您按 ctrl+c 时,SIGINT 会传递到整个进程组。
  • 当您分叉新进程时,信号处理程序不会传递给新进程

因此如果您想手动控制子进程信号,则必须更改进程的 GID。

  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

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:

  • When 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

  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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无可置疑 2024-12-04 20:29:15

您始终可以让孩子忽略 INT 信号。

You could always have the child ignore the INT signal.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文