A
A
I am getting intermittent unexpected result from waitpid on Solaris 9
running Perl 5.8.8.
Here is the scenario (the bare bones code is below).
Program_A, written in Perl, is invoked about a million times every
day. Most of the times, it invokes (using fork-exec) Program_B which
is written in C++. Program_A uses waitpid to get the exit code of
Program_B.
It works fine most of the times, but about a few dozen times every
day, the waitpid apparently fails and when it fails, I get
$? is -1
$! is "No child processes"
In all of the cases I have investigated, the child process, Program_B,
started and completed gracefully with "exit(0)" and of course, the pid-
s match from the trace log of both processes.
The output, from the code below, in such case is
Child pid=5196, exitCode=0xffffffff (No child processes)
Program_A itself is transient and short lived, and, depending on its
input, executes Program_B at most once.
What am I doing wrong?
How to detect and correct this?
Thanks for your help.
# ------------------------------------------- begin code
-------------------------------------------------
#!/usr/local/bin/perl
# program_A
my $cpid;
my $ec = undef;
my $em = undef;
sub getChildStatus
{
my $tc = undef;
my $tm = undef;
my $r = undef;
while ( 1 ) {
$r = waitpid($cpid, 0);
$tc = $?;
$em = $!;
last if ( -1 == $r || $r == $cpid );
print STDERR "waitpid($cpid, 0) returned $r ( $? )\n";
}
if ( $cpid == $r ) {
$ec = $tc;
$em = $tm;
}
}
sub sigCLDhandler
{
my $sig = shift;
print STDERR "caught SIG $sig\n";
getChildStatus;
}
sub runIt
{
my $oldSigCld = $SIG{CLD};
local $SIG{CLD} = \&sigChldHandler;
$cpid = fork;
if ( ! defined $cpid ) { print STDERR "fork failed [ $! ]\n";
return; }
if ( 0 == $cpid ) {
print STDERR "child pid $$ starting\n";
exec program_B, .. .. ..;
print STDERR "child pid $$: exec failed [$!], exiting with -1\n";
exit(-1);
} # 0 == $cpid i.e. the child
getChildStatus; # only the parent reaches here
$SIG{CLD} = $oldSigCld ;
} # runIt
#
# main
#
runIt;
if ( $ec ) {
printf STDERR "Child pid=$cpid exitcode=%#08x msg=(%s)\n", $ec, $em;
}
# ------------------------------------------- end code
-------------------------------------------------
running Perl 5.8.8.
Here is the scenario (the bare bones code is below).
Program_A, written in Perl, is invoked about a million times every
day. Most of the times, it invokes (using fork-exec) Program_B which
is written in C++. Program_A uses waitpid to get the exit code of
Program_B.
It works fine most of the times, but about a few dozen times every
day, the waitpid apparently fails and when it fails, I get
$? is -1
$! is "No child processes"
In all of the cases I have investigated, the child process, Program_B,
started and completed gracefully with "exit(0)" and of course, the pid-
s match from the trace log of both processes.
The output, from the code below, in such case is
Child pid=5196, exitCode=0xffffffff (No child processes)
Program_A itself is transient and short lived, and, depending on its
input, executes Program_B at most once.
What am I doing wrong?
How to detect and correct this?
Thanks for your help.
# ------------------------------------------- begin code
-------------------------------------------------
#!/usr/local/bin/perl
# program_A
my $cpid;
my $ec = undef;
my $em = undef;
sub getChildStatus
{
my $tc = undef;
my $tm = undef;
my $r = undef;
while ( 1 ) {
$r = waitpid($cpid, 0);
$tc = $?;
$em = $!;
last if ( -1 == $r || $r == $cpid );
print STDERR "waitpid($cpid, 0) returned $r ( $? )\n";
}
if ( $cpid == $r ) {
$ec = $tc;
$em = $tm;
}
}
sub sigCLDhandler
{
my $sig = shift;
print STDERR "caught SIG $sig\n";
getChildStatus;
}
sub runIt
{
my $oldSigCld = $SIG{CLD};
local $SIG{CLD} = \&sigChldHandler;
$cpid = fork;
if ( ! defined $cpid ) { print STDERR "fork failed [ $! ]\n";
return; }
if ( 0 == $cpid ) {
print STDERR "child pid $$ starting\n";
exec program_B, .. .. ..;
print STDERR "child pid $$: exec failed [$!], exiting with -1\n";
exit(-1);
} # 0 == $cpid i.e. the child
getChildStatus; # only the parent reaches here
$SIG{CLD} = $oldSigCld ;
} # runIt
#
# main
#
runIt;
if ( $ec ) {
printf STDERR "Child pid=$cpid exitcode=%#08x msg=(%s)\n", $ec, $em;
}
# ------------------------------------------- end code
-------------------------------------------------