2015-11-04 6 views
0

У меня есть скрипт perl с несколькими дочерними процессами (создан с использованием fork()). Каждый ребенок спит, затем выполняет некоторую обработку (несколько вызовов system()). Под окнами, когда я нажимаю Ctrl + C, я вижу, что сигнал был пойман, тогда скрипт ждет, когда дети закончатся, и после этого выйдет. Я хочу реплицировать это поведение в linux (catch sigint, позволить детям завершить и выйти из основного сценария/процесса).Подождите, пока дети завершатся, если родительский перехват SIGINT

Как подождать, пока все дети закончатся, прежде чем убить родителя? Возможно ли выйти из основного сценария/убить родителя, но разрешить ли дети заполняться в фоновом режиме?

Я нашел Child process receives parent's SIGINT, и кажется, что SIGINT распространяется на детей (группа процессов), поэтому, чтобы этого избежать, мне пришлось бы установить ребенка в другую группу процессов.

$SIG{'INT'} = sub { 
    print "Caught Ctrl+C\n"; 
    die "Stopping..."; 
}; 

++$|; 

print "Start\n"; 
for($i=0; $i < 500; $i++) { 
    sleep 3; 
    $childPid = fork(); #fork a process 
    if($childPid == 0){ 
     print "Child $i...\n"; 
     sleep 10; 
     system("echo finishing"); 
     print "Exit child $i\n"; 
     exit; 
    } 
} 

Я также попытался включить это в блоке обработки SIGINT, но цикл не приостановлена, создаются таким образом, новые дочерние процессы и родитель не умирает.

# I used my $parentPid = $$; (before the for loop) to get the parent pid. 

if ($$ = $parentPid){ 
    foreach $var (@pids) { 
     $pid = waitpid($var ,0); 
    } 

EDIT:

Пытался установки детского SIGINT обработчика в игнор, и она работает, как ожидалось. В родительском обработчике я:

$SIG{'INT'} = sub { 
    print "Caught Ctrl+C by $$\n"; 
    # while($result != -1){ 
     # $result = wait(); 
    #} 
    die "Stopping..."; 
}; 

а) Если включить строки комментариев сценарий ждет детей, чтобы закончить, а затем завершает свою работу.

б) Но если я комментирую линии «ждать» Я предполагаю, что это работает как это

  1. выходов сценария и родительский процесс завершается
  2. дети продолжают работать в фоновом режиме и дисплей «Выход из дочернего» сообщения, как ожидалось до выхода.

Я понимаю а) случай, но как работает б), объясните, почему это не порождает процессы зомби?

ответ

0

Под окнами, когда я нажимаю Ctrl + C, я вижу, что сигнал был пойман, а затем скрипт ждет, пока дети завершатся, и после этого выйдет.

Я думаю, что это побочный эффект реализации псевдо-вилки.

Как подождать, пока все дети закончатся, прежде чем убить родителя?

Самый простой способ игнорировать SIGINT У детей и wait/waitpid в родительском SIGINT обработчика.

Я также попытался включить это в блок обработки SIGINT, но цикл for не приостанавливается, поэтому создаются новые дочерние процессы, и родительский элемент не умирает.

Я думаю, вы имели в виду $$ == $parentPid (сравнение вместо назначения). Кроме того, не очень полезно указать, какого ребенка вы ждете, если вы все равно их ожидаете.

+0

Да, моя ошибка с «==», теперь родительские выходы, и я получаю сообщения «Выход из ребенка», но сразу же, возможно, процесс сна у детей завершается, а остальная часть кода продолжается ? Я бы хотел, чтобы они спали, как указано ... И в отношении ожидания ... я должен использовать wait() - это будет ждать всех детей? –

+0

Да, сигналы прерывают спящий режим, поэтому вы должны установить обработчик 'SIGINT' для игнорирования в дочерних элементах (' $ SIG {INT} = 'IGNORE'') –

+0

Пробовал IGNORE для дочерних процессов, и он работает, но я до сих пор неясно о «ожидании». Посмотрите на edit –

Смежные вопросы