2015-10-06 1 views
1

Я использую Cygwin в Windows 7 (хотя такая же проблема может быть применима и к родной среде Linux).Как я могу убить процесс, который породил ребенка с помощью system()?

Родительский процесс, который, случается, является программой Ruby, но я предполагаю, что такая же проблема возникла бы, если бы это было чистое приложение C - использует system() для выполнения внешней (возможно, продолжительной) команды.

Пока эта внешняя программа работает, родительский процесс убивается. Детский процесс все еще жив. Что я могу сделать, чтобы гарантировать, что детский процесс также будет убит?

Здесь сценарий «песочница», чтобы объяснить эту проблему: В одном окне терминала, я выполнить следующую команду:

ruby -e 'puts $$; system("sh")' # Could also be a C program 

Очевидно, что это висит вечно по команде sh, после того, как напечатали идентификатор процесса.

Теперь я пытаюсь из другого окна терминала

kill -INT ... 

убить процесс Ruby. Используя procps или ps, я могу проверить, что этот процесс все еще жив. Теперь я использую

kill -TERM .... 

По-прежнему процесс не убивается. Наконец, я делаю a

kill -KILL .... 

и, конечно же, выполняет эту работу. Процесс Ruby убит, но дочерний процесс (sh) все еще жив.

Я понимаю, что это ожидаемое поведение, но что является простым и надежным обходным решением?

Я попытался установить сеанс и называется Process.setsid перед выполнением system, но я получаю сообщение об ошибке

`setsid ': Операция не допускается (Errno :: EPERM)

Может быть setsid не является доступный на Cygwin, что меня не удивит, потому что обработка Windows очень отличается.

Любые другие идеи, что я мог попробовать? Кстати, код, как предполагается, будет портирован на Linux в конечном итоге, поэтому, если это возможно, я хотел бы использовать решение, которое работает под Cygwin и Linux.

+0

вы пытались 'killall -9 ruby'? – juned

+0

О, Боже мой! Это убьет все мои рубиновые процессы !!! Ни одно решение для моей проблемы (так как это приведет к уничтожению только родительского процесса, а не его дочернего элемента, а также приведет к уничтожению всех других рубиновых процессов, порожденных из оболочки Cygwin! – user1934428

+0

Общее решение в Windows состоит в том, чтобы поместить ребенка в объект задания Если вы можете разумно сделать это с помощью ruby ​​/ cygwin, я не знаю. –

ответ

1

Посмотрите на this чудесном блоге о асинхронной обработке в Ruby, он предлагает использовать вилку в Linux и икре в Windows, я предлагаю попробовать как в Cygwin

pid = fork do 
    exec 'sleep', '10' 
end 
Process.kill pid 
+0

Я был думая об этом.Используя этот подход, я должен где-то хранить идентификатор процесса для дочернего элемента (переменный pid в вашем примере), чтобы процесс убийцы мог его извлечь. Я просто надеялся, что решение, в котором я могу использовать 'system' для разветвления ребенка, было бы возможно ... – user1934428

+0

Спасибо за ссылку на блог. Это действительно хорошее чтение! – user1934428