2010-07-14 15 views
7

Was geht hier vor? Ich dachte, SIGINT würde an die Vordergrundprozessgruppe gesendet werden.Warum wird SIGINT hier nicht erwischt?

(ich glaube, vielleicht, dass das System() ist eine Shell ausgeführt wird, die eine neue Prozessgruppe für das Kind Prozess schafft? Kann das jemand bestätigen?)

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

schlug dann ctrl + d dann ctrl + c sofort und beachten Sie, dass "Signal abgefangen" nie gedruckt wird.

Ich fühle mich wie das ist eine einfache Sache ... wie auch immer, um dies zu umgehen? Das Problem ist, dass beim Ausführen einer Reihe von Befehlen über das System hält Strg + C bis alle Iterationen abgeschlossen sind (weil Perl nie das SIGINT erhält) und ist eher ärgerlich ...

Wie kann dies umgangen werden? (Getestet habe ich bereits Gabel() direkt und verstehen, dass dies funktioniert ... das ist keine akzeptable Lösung zu diesem Zeitpunkt)

UPDATE: Bitte beachten Sie, das hat nichts mit „schlafen“ zu tun, nur die Tatsache, dass der Befehl eine willkürlich lange Zeit benötigt, um zu laufen, was erheblich mehr ist als die der umgebenden Perle. So sehr, dass das Drücken von Strg + C an den Befehl gesendet wird (wie in der Vordergrundprozessgruppe?) Und es irgendwie schafft, niemals an Perl gesendet zu werden.

Antwort

4

von perldoc system:

Seit SIGINT und SIGQUIT während der Ausführung des Systems ignoriert werden, wenn Sie Ihr Programm erwartet auf Empfang dieser Signale zu beenden, müssen Sie ordnen sich selbst zu tun, so auf der Grundlage des Rückgabewert.

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

Wenn Sie manuell mögen System Scheitern überprüfen, können Sie alle möglichen Ausfall Modi überprüfen, indem $ Inspektion? wie folgt aus:

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; 
} 

Alternativ können Sie den Wert von $ {^ CHILD_ERROR_NATIVE} mit dem W *() ruft aus dem POSIX-Modul

+3

ich denke, ich muss die Dokumentation noch einmal lesen: -/Danke. – dlamotte

+1

Ich würde hinzufügen, dass der Grund, warum Sie den Rückgabewert des Kindes untersuchen müssen, ist, dass Ihre Shell die^c/INT an die gesamte Prozessgruppe, Perl und Kinder liefert, in diesem Fall beendet Ihr Kind "Schlaf 10". Wenn Sie einfach "-INT $ perl_pid" von einer anderen Shell entfernen, wird Perl Ihnen gerne SIG_IGN geben. – pilcrow

0

ich nicht ganz bekommt, was Sie versuchen, hier zu erreichen ... aber haben Sie versucht, einfach im Vergleich zu:

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

Können Sie erklären, welche Auswirkungen Sie versuchen, zu gehen, und Warum rufen Sie die Shell an? Können Sie einfach direkt in das externe Programm einwählen, ohne die Shell einzubeziehen?

+0

siehe meine UPDATE Abschnitt "sleeping" inspizieren hat nichts damit zu tun ... es ist einfach ein Platzhalter für irgendeinen willkürlichen Prozess. Es könnte leicht mit "grep etwas" geschaltet werden, das für immer hängen wird, da es erwartet, Daten von stdin zu lesen – dlamotte

+0

@ xyld: Ich weiß, dass der Schlaf ein Platzhalter ist. Ich habe gefragt, warum du die Shell aufrufen musst, anstatt deinen Prozess direkt aufzurufen. – Ether

+0

Ich bin nicht explizit, aber der Perl-Interpreter kann es als Teil von "System()" tun. – dlamotte

Verwandte Themen