межпроцессная обработка сигналов в Ruby - PullRequest
2 голосов
/ 03 августа 2011

Я запускаю этот скрипт:

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

Вы можете видеть, что "INT" передается каждому процессу и Process.kill "INT", t пытается убить процесс, который уже умер. Есть ли способ сделать так, чтобы пользовательский сигнал 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

1 Ответ

0 голосов
/ 03 августа 2011

Вы всегда можете заставить ребенка игнорировать сигнал INT.

...