Почему SIGINT не попадают сюда? - PullRequest
7 голосов
/ 14 июля 2010

Что здесь происходит?Я думал, что SIGINT будет отправлен в группу процессов переднего плана.

(я думаю, возможно, что system () запускает оболочку, которая создает новую группу процессов для дочернего процесса? Может кто-нибудь подтвердить это?)

% perl
local $SIG{INT} = sub { print "caught signal\n"; };
system('sleep', '10');

Затем нажмите Ctrl + D, затем Ctrl + C немедленно и заметьте, что «пойманный сигнал» никогда не печатается.

Мне кажется, что это просто ... все равно работатьвокруг этого?Проблема заключается в том, что при запуске набора команд через систему происходит удержание Ctrl + C до тех пор, пока все итерации не будут завершены (поскольку Perl никогда не получает SIGINT), и это довольно раздражает ...

Как это можно обойти?(Я уже тестировал использование fork () напрямую и понимаю, что это работает ... в настоящее время это неприемлемое решение)

ОБНОВЛЕНИЕ : обратите внимание, здесь ничего нет , что касается «сна», только того факта, что выполнение команды занимает произвольно много времени, что значительно больше, чем у perl вокруг нее.Настолько, что нажатие ctrl + c отправляется в команду (как в группе процессов переднего плана?) И каким-то образом удается ее никогда не отправлять в perl.

Ответы [ 2 ]

4 голосов
/ 14 июля 2010

из perldoc system :

Поскольку SIGINT и SIGQUIT игнорируются во время работы системы, если вы ожидаете, что ваша программа завершит работу при получении этих сигналов, вам потребуетсяорганизовать это самостоятельно, основываясь на возвращаемом значении.

@args = ("command", "arg1", "arg2");
system(@args) == 0
   or die "system @args failed: $?"

Если вы хотите вручную проверить отказ системы, вы можете проверить все возможные режимы отказа, просмотрев $?как это:

if ($? == -1) {
    print "failed to execute: $!\n";
}
elsif ($? & 127) {
    printf "child died with signal %d, %s coredump\n",
       ($? & 127),  ($? & 128) ? 'with' : 'without';
}
else {
    printf "child exited with value %d\n", $? >> 8;
}

В качестве альтернативы, вы можете проверить значение $ {^ CHILD_ERROR_NATIVE} с помощью вызовов W * () из модуля POSIX

0 голосов
/ 14 июля 2010

Я не совсем понимаю, чего вы пытаетесь достичь здесь ... но вы пытались просто сравнить с:

perl -wle'local $SIG{INT} = sub { print "caught signal"; }; sleep 10;'

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

...