Retrieving command exit code with open3

R

Ryan

I'm using code similar to the following to run a command and grab the
output from both STDOUT and STDERR separately:

local (*IN, *OUT, *ERR);
my $pid = IPC::Open3::eek:pen3(*IN, *OUT, *ERR, $cmd, @args);
print IN join "\n", @input;
close IN;
my @out = <OUT>;
my @err = <ERR>;
close OUT;
close ERR;
waitpid $pid, 0;
print "exit: $?\n"

Most of the time this works, but occasionally waitpid will return -1
and $? will also be set to -1 meaning that there is no child process.
Presumably the child exited before my call to waitpid.

What can I do to reliably grab the exit code?

Thanks,
-Ryan
 
X

xhoster

Ryan said:
I'm using code similar to the following to run a command and grab the
output from both STDOUT and STDERR separately:

local (*IN, *OUT, *ERR);
my $pid = IPC::Open3::eek:pen3(*IN, *OUT, *ERR, $cmd, @args);
print IN join "\n", @input;
close IN;
my @out = <OUT>;
my @err = <ERR>;

This is liable to deadlock.
close OUT;
close ERR;
waitpid $pid, 0;
print "exit: $?\n"

Most of the time this works, but occasionally waitpid will return -1
and $? will also be set to -1 meaning that there is no child process.
Presumably the child exited before my call to waitpid.

If the child tries to exit before the waitpid, it should become a zombie
and stick around for the waitpid. I would have thought your open3 was
failing, but such failure is supposed to die, not return false. However, I
don't really undertand that last sentence there and maybe that is the
source of the problem:

from IPC::Open3

open3() returns the process ID of the child process. It doesn't
return on failure: it just raises an exception matching "/^open3:/".
However, "exec" failures in the child are not detected. You'll have
to trap SIGPIPE yourself.

Xho
 
R

Ryan

This is liable to deadlock.

Thanks; I'm aware of the select-based workaround; the code is more
demonstrative.
If the child tries to exit before the waitpid, it should become a zombie
and stick around for the waitpid.

This is interesting since it doesn't appear to be the behavior I'm
experiencing. About 20% of the time, waitpid is returning -1. The
command being executed is identical to previous test runs which
successfully provide an exit code of 0 in $?.
However, I
don't really undertand that last sentence there and maybe that is the
source of the problem:

You can ignore that last sentence. I wasn't aware of the zombie
behavior.
open3() returns the process ID of the child process. It doesn't
return on failure: it just raises an exception matching "/^open3:/".
However, "exec" failures in the child are not detected. You'll have
to trap SIGPIPE yourself.

It seems as though the command is likely to be executing successfully
since the same test case seems to succeed and fail at random, but I'll
explore this avenue further.

Thanks again
-Ryan
 
X

xhoster

Ryan said:
Thanks; I'm aware of the select-based workaround; the code is more
demonstrative.


This is interesting since it doesn't appear to be the behavior I'm
experiencing. About 20% of the time, waitpid is returning -1.

Is it possible some other part of your code is messing
around with $SIG{CHLD}?

If you replace $cmd with something dead simple (like "echo foo") do
you still these failures?

The
command being executed is identical to previous test runs which
successfully provide an exit code of 0 in $?.


Hmmm. open3 has some OS-specific code paths. What OS are you on?

What is in @out and @err for those times when you get -1? How does
it compare to the contents of those variables when you get 0? (If the
open3 code encounters an error after it does the fork but before it does
the exec of the command you are running, it can print useful diagnostics to
one of two stream. However, I don't see how this can give a -1 for
waitpid.)

You can ignore that last sentence. I wasn't aware of the zombie
behavior.

I didn't mean your last sentence, I meant the last sentence of the POD I
quoted, about SIGPIPE.

Xho
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top