Mise à jour: Merci à @zdim pour me rappeler de vérifier le signal SIGPIPE
. Voici une mise à jour de ma réponse qui vérifie également SIGPIPE
:
J'ai fait un test simple en utilisant start
, pump
et finish
. Voici le script principal p.pl
que je:
use feature qw(say);
use strict;
use warnings;
use IPC::Run;
my $child_in;
my $child_out;
my $child_err;
my $child_name = shift;
my $harness = eval {
IPC::Run::start [ $child_name ], \$child_in, \$child_out, \$child_err;
};
if ([email protected]) {
chomp [email protected];
die "Caught exception: '[email protected]'";
}
for (1..2) {
$child_in = "Joe$_\n";
say "Parent sleeping for 1 second..";
sleep 1;
eval {
local $SIG{PIPE} = sub {
die "Parent received SIGPIPE. "
. "Child is either dead or has closed its input pipe\n";
};
say "Sending data to child..";
my $result = $harness->pump;
say "IPC::Run::pump() returned: ", $result ? "TRUE" : "FALSE";
};
if ([email protected]) {
chomp [email protected];
say "IPC::Run::pump() failed: '[email protected]'";
last;
}
say "\$child_in = '$child_in'";
say "\$child_out = '$child_out'";
}
say "Finishing harness..";
my $res = eval {
local $SIG{PIPE} = sub {
die "Parent received SIGPIPE. "
. "Child is either dead or has closed its input pipe\n";
};
$harness->finish;
};
if ([email protected]) {
chomp [email protected];
die "IPC::Run::finish() failed: '[email protected]'\n";
}
printf "IPC::Run::finish() returned: '%s'\n", $res ? "TRUE" : "FALSE";
chomp $child_out;
say "STDOUT from child: '$child_out'";
chomp $child_err;
say "STDERR from child: '$child_err'";
say "Child returned exit code: ", $harness->result;
say "Parent exited normally.."
je trois scripts enfants différents:
child.pl:
#! /usr/bin/env perl
use feature qw(say);
use strict;
use warnings;
my $reply = <STDIN>;
chomp $reply;
say "Hello $reply";
my $reply2 = <STDIN>;
chomp $reply2;
say "Got second reply: $reply2";
exit 0;
et sortie:
$ p.pl child.pl
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() returned: TRUE
$child_in = ''
$child_out = ''
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() returned: TRUE
$child_in = ''
$child_out = ''
Finishing harness..
IPC::Run::finish() returned: 'TRUE'
STDOUT from child: 'Hello Joe1
Got second reply: Joe2'
STDERR from child: ''
Child returned exit code:
Parent exited normally..
enfant2.pl:
#! /usr/bin/env perl
use feature qw(say);
use strict;
use warnings;
my $reply = <STDIN>;
chomp $reply;
say "Hello $reply";
die "Child exception\n";
et sortie:
$ p.pl child2.pl
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() returned: TRUE
$child_in = ''
$child_out = ''
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() failed: 'Parent received SIGPIPE. Child is either dead or has closed its input pipe'
Finishing harness..
IPC::Run::finish() failed: 'Parent received SIGPIPE. Child is either dead or has closed its input pipe'
child3.pl:
#! /usr/bin/env perl
use strict;
use warnings;
close \*STDIN;
close \*STDOUT;
close \*STDERR;
sleep 5;
exit 2;
et sortie:
$ p.pl child3.pl
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() failed: 'ack Parent received SIGPIPE. Child is either dead or has closed its input pipe'
Finishing harness..
IPC::Run::finish() failed: 'Parent received SIGPIPE. Child is either dead or has closed its input pipe'
Donc, pour ces tes ts, il semble que le signal SIGPIPE
peut être utilisé pour vérifier si un enfant est vivant ou a fermé son tube d'entrée. Notez que si vous essayez d'appeler pump()
après la fermeture d'un enfant, la sortie précédente de l'enfant est perdue, voir l'exemple child2.pl
.
Belle prise de 'SIGPIPE'. Je pense que c'était ce qui me manquait :) –
@ HåkonHægland A droite, le 'SIGPIPE' est le bouchon du spectacle. Mais c'est encore compliqué. Il peut être plus simple de vérifier avant chaque appel en utilisant une combinaison de 'result' et' pumpable' (plus le gestionnaire 'SIGPIPE'). – zdim
@ AndrzejA.Filip J'ai mis à jour la réponse avec un commentaire sur la vérification directe en utilisant 'result' +' pumpable' (+ 'SIGPIPE' handler). J'ai également édité quelques commentaires pour l'exactitude. J'ai confirmé dans mes tests que l'approche principale dans la réponse traite tous les cas, pratiquement comme elle est. Faites-nous savoir comment cela fonctionne pour vous. La réponse de @ Håkon a également été mise à jour. – zdim