patternMinor
The right way to use IPC::Open3 in Perl
Viewed 0 times
theperlopen3wayipcuseright
Problem
Here is the function which does exactly what is specified by its name:
After the script successfully completes its job and before Perl interpreter exits, I get this message in the terminal:
stty: standard input: Bad file descriptor
It would be nice to have your opinion about the code correctness, and get a piece of advice about how to avoid that message, as a bonus.
UPDATE: The message mentioned gone away when I replaced '\*STDIN' arg with 'undef'.
Major update: It appears that this code is not functioning properly. It mixes stderr and stdout from child process, and returns e
sub runCmd_getStdoutStderrAndExitCode(@)
{
my @cmd = @_;
# fork a child
my ($child_pid, $child_stdout, $child_stderr);
eval
{
$child_pid = open3(\*STDIN, # is /dev/null when collectl is a daemon, UPDATE: can pass 'undef' here
$child_stdout,
$child_stderr,
@cmd);
};
if ($@ =~ /^open3:/)
{
syslog(LOG_ERR, 'Error in "%s" : %s', "@cmd", $@);
return (undef, undef, -1);
}
# result buffers
my $stdout = '';
my $stderr = '';
# read into result buffers avoid blocking
my $selector = IO::Select->new();
$selector->add($child_stdout, $child_stderr);
while (my @ready = $selector->can_read(SOME_TIMEOUT_CONSTANT))
{
foreach my $fh (@ready) {
my $target_buf = ($fh == $child_stdout)
? \$stdout
: \$stderr;
if (!sysread($fh, $target_buf, 4096, length($target_buf)))
{
$selector->remove($fh);
close $fh;
}
}
}
close $_ for ($selector->handles());
my $finished = waitpid($child_pid, WNOHANG);
return ($stdout, $stderr, $?) if $finished;
if (kill 'TERM' => $child_pid) {
# hang until SIGTERM is processed then bury child process
waitpid($child_pid, 0);
} else {
syslog(LOG_WARNING, 'Error sending TERM to child process "%s"', "@cmd");
}
return ($stdout, $stderr, -1);
}After the script successfully completes its job and before Perl interpreter exits, I get this message in the terminal:
stty: standard input: Bad file descriptor
It would be nice to have your opinion about the code correctness, and get a piece of advice about how to avoid that message, as a bonus.
UPDATE: The message mentioned gone away when I replaced '\*STDIN' arg with 'undef'.
Major update: It appears that this code is not functioning properly. It mixes stderr and stdout from child process, and returns e
Solution
as it say in the IPC::Open3 documentation, the filehandle for STDERR cannot be autovivified. You need to
to create a file handle before opening your command.
use Symbol qw/ gensym /; my $stderr = gensym;to create a file handle before opening your command.
Code Snippets
use Symbol qw/ gensym /; my $stderr = gensym;Context
StackExchange Code Review Q#84496, answer score: 5
Revisions (0)
No revisions yet.