2016-04-30 9 views
7

Ich habe das folgende Problem, das ich in diesen beiden Mini-Perl-Skripten rekonstruiert habe. Dies ist das Hauptskript:Senden eines Signals an ein Perl-Skript, während es ein Dateihandle schließt

#!/usr/bin/perl 
$SIG{INT} = \&signal_handler_one; 
open(my $pipe, "|-", "/home/pa/Desktop/POC2"); 
close $pipe; 
sub signal_handler_one{ 
    print "This is expected to print\n"; 
} 

In der dritten Zeile es ein Rohr zu diesem Skript öffnet:

#!/usr/bin/perl 
$SIG{INT} = \&signal_handler_two; 
sleep(10); 
sub signal_handler_two{ 
    print "This isn't expected to print\n"; 
} 

Das Problem ist, dass, wenn ich das erste Skript zu starten und dann SIGINT an ihn schicken, während es schließt die Leitung auf Leitung 4, der signal_handler_two wird anstelle von signal_handler_one ausgelöst. Warum verhält es sich so? Gibt es einen Weg dazu (mein Ziel ist es, signal_handler_one zur Ausführung zu bringen).

Bearbeiten: Ich habe ursprünglich das Signal auf dem Terminal mit Strg + C gesendet, was bewirkt, dass "Dies wird nicht erwartet zu drucken" zu drucken. Aber wenn ich das Signal mit kill zum Elternprozess von einem anderen Terminal aus aussende, ignoriert es es einfach.

Edit 2: Ich löste es schließlich von nicht offen mit der Leitung, sondern durch manuelle Forking, execing und dann statt Aufruf von nur Nähe auf dem Kind warten, um zu bekommen . Jetzt scheint alles gut zu funktionieren. Es scheint, dass dieses Verhalten für meine Umgebung spezifisch war, aber wenn jemand diesen Fehler reproduzieren könnte, lass es mich wissen.

+1

Also ist das zweite Skript 'POC2'? Wie schickst du das Signal genau? Woher weißt du, dass das erste Skript die Pipe schließt? – Borodin

+0

Ich sende es mit Strg + C am Terminal. Der Close-Call blockiert, bis der zweite Prozess beendet wird. Es gibt ein 10 Sekunden langes Fenster, in dem ich Strg + C zur richtigen Zeit senden kann. Ja, POC2 ist das zweite Skript. – Void

+1

Ich denke, Sie werden feststellen, dass Ctrl-C das Signal an den zuletzt aktiven Prozess sendet. Sie können selektiver sein, indem Sie den ersten Prozess veranlassen, seine PID mit 'print '$$ \ n" 'zu melden und dann' kill -s INT 1234' in der Befehlszeile, wobei' 1234' durch die tatsächliche PID ersetzt wird. – Borodin

Antwort

3

Ich kann das Verhalten, das Sie beobachten, nicht reproduzieren. Als ich CTRL-C im Terminal drücken, sowohl das Kind und die Eltern sofort erhält SIGINT:

use diagnostics; 
use feature qw(say); 
use strict; 
use warnings; 

$SIG{INT} = sub { say "This is expected to print"; die }; 
my $pid = open (my $pipe, "|-", "script.pl"); 
say "PID = $pid"; 
eval { 
    say "Closing.."; 
    my $close_ok = close $pipe; # Note "close" here waits for child to exit 
    if (! $close_ok) { 
     say "Error closing: $!"; 
    } 
    else { 
     say "Close done."; 
    } 
}; 
if ([email protected]) { 
    say "Parent caught SIGINT."; 
} 

wo script.pl ist:

#! /usr/bin/env perl 

use feature qw(say); 
use strict; 
use warnings; 

$SIG{INT} = sub { die }; 
eval { 
    say "Sleeping.."; 
    for (1..5) { 
     sleep 1; 
     say $_; 
    } 
}; 
if ([email protected]) { 
    say "Child caught SIGINT."; 
    exit; 
} 

der Ausgang des ersten Programms in dem Terminal läuft (gnome-terminal auf Ubuntu 16.04) ist:

PID = 1746 
Closing.. 
Sleeping.. 
1 
2 
^CThis is expected to print 
Child caught SIGINT. 
Parent caught SIGINT. 
Uncaught exception from user code: 
    refcnt: fd -1 < 0 

Beachten Sie, dass es eine abgefangene Ausnahme ist refcnt: fd -1 < 0. Ich habe keine Ahnung, was das ist. Vielleicht weil close nicht erfolgreich war?

+0

Ich denke, dann stimmt etwas mit meiner Umgebung nicht. Wenn ich deinen Code ausführe, drucke es nicht "Eltern gefangenes SIGINT.". – Void

+0

@Void, nein, Ihre Umgebung ist korrekt. Die Zeile "Parent" wird nicht angezeigt, weil Sie Ihr SIGINT während des "close" (das SIGINT ignoriert) (http://stackoverflow.com/a/4719492/132382) senden. Diese Antwort macht etwas anderes - Senden des SIGINT zu früh oder zu spät, z. – pilcrow

+0

@pilcrow Ich war mir sicher, dass ich das Signal während 'close' gesendet habe. Sie können auf der Ausgabe sehen, dass es 'Closing..' sagt und dann wartet es auf das Programm zu beenden. Dies muss in 'close' geschehen, da die print-Anweisung nach dem' close' nicht angezeigt wird. Nach 5 Sekunden wird 'close' zurückgegeben, wenn ich nicht'CTRL-C' drücke. So interpretiere ich die Ausgabe . Ich bin neugierig, warum du meinst, es sendet 'SIGINT' nicht während' close'? –

Verwandte Themen