fiberhalo has asked for the wisdom of the Perl Monks concerning the following question:
Why is it that when the sigCHLD signal is ignored, system() always returns -1?
-------------------- prog1.pl -----------------
#!/usr/bin/perl
$SIG{'CHLD'} = 'IGNORE';
system('prog2.pl');
print "return value is ", $?>>8, "\n";
-------------------- prog2.pl ------------------
#!/usr/bin/perl
exit 5;
If $SIG{'CHLD'} = 'IGNORE' is commented out, the return value is 5, which is what I expect. If it is left in,
the return value is -1.
Is ignoring sigCHLD not recommended when using system?
I tested this on Linux, FreeBSD and Solaris with two versions of perl, all with the same results, so I assume this is something that is not really a bug. I've just never run across this before, and am looking for some insight.
20031105 Edit by Corion: Added CODE tags
Re: why does ignoring sigCHLD corrupt return value from system()?
by ehdonhon (Curate) on Nov 05, 2003 at 00:56 UTC
|
There was some revisions on $SIG{CHLD} = 'IGNORE' that went into Perl 5.8.1, I believe. The short of it was that on some operating systems prior to 5.8.1, doing a SIG{CHLD} = 'IGNORE' could cause Perl to wait() for the forked child process twice and cause an infinite hang.
If you are using something prior to 5.8.1, you might be seeing another symptom of the same problem. If you are using post-5.8.1, it could be that the patch broke something else.
If you are the most recent version of Perl, it sounds like something you might want to submit a perlbug for. When you do, you might want to refer to bug #
18849
| [reply] [Watch: Dir/Any] |
Re: why does ignoring sigCHLD corrupt return value from system()?
by sauoq (Abbot) on Nov 05, 2003 at 01:00 UTC
|
I can reproduce this with 5.6.1 and 5.005_02 on Solaris 7. And with 5.8.0, 5.6.1, and 5.005_03 on Solaris 8.
But I can't with 5.8.0 on Linux 2.4.18 (libc-2.2.93).
-sauoq
"My two cents aren't worth a dime.";
| [reply] [Watch: Dir/Any] |
|
Tested on Linux:
- RH7.2, i386, perl 5.6.1, kernel 2.4.20, glibc 2.2.4:
I get the expected result, ie -1 if system() fails and 5 if
prog2.pl is run, independently of how sigCHILD is handled.
- RH9a, i386, perl 5.8.0, kernel 2.4.20, glibc 2.3.2: when
prog2.pl get executed, ignoring sigCHILD returns -1 instead
of 5
It definitely looks like a bug.
| [reply] [Watch: Dir/Any] |
Re: why does ignoring sigCHLD corrupt return value from system()?
by TheHobbit (Pilgrim) on Nov 05, 2003 at 01:12 UTC
|
Hi,
There is an error in your code: you wrote system("prog2.pl") which does not invoke prog2.pl unless you have '.' (the current directory) in your PATH (which should be avoided).
By replacing your instruction with system("./prog2.pl") I get a return code of 5 both with and without SIGCHLD ignored. Just as I expected.
I expected this result because perl system emulates C system(3), and the man page of the latter states that:
During execution of the command, SIGCHLD will be blocked,
and SIGINT and SIGQUIT will be ignored.
That is to say: system install its own SIGCHLD handler, which is needed exactly for capturing the exit status.
I join Abigail-II in asking which version of perl, operating system and kernel are you using.
By the way, why should ignoring SIGCHLD be recommended when using system? Never heard that...
Hoping this helps
Leo TheHobbit
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
By replacing your instruction with system("./prog2.pl") I get a return code of 5 both with and without SIGCHLD ignored.
But what did you get before you made that replacement? I'm guessing -1 in both cases and that your platform just isn't one of the ones that exhibits this.
By the way, why should ignoring SIGCHLD be recommended when using system? Never heard that...
I don't think that such a "recommendation" is suggested by the original post. I doubt he was ignoring SIGCHLD because he was using system(); I'd bet he just ran into this in a program that happened to do both. So, the question is: must we recommend never ignoring SIGCHLD when using system()?
-sauoq
"My two cents aren't worth a dime.";
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Hi,
The fact that $SIG{CHLD} is set to wichever value the user chose must not change the behavior of system as stated in
perlfunc,
expecially where it states that:
Does exactly the same thing as "exec LIST", except that a fork is done first, and the parent process waits for the child process to complete.
The parent process needs to intercept SIGCHLD in order to wait(2) for the child process to complete.
As I stated above, this implies that the value of $SIG{CHLD} must be localized to same value during the execution of system, and so the user value of it outside that execution is (or shuld be) irrelevant.
Just my 5 (euro) cents.
Leo TheHobbit
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
Thanks everyone for the assistance/suggestions. This isn't a major issue for me or anything. I just happened to notice this when I added a system() to an existing program that already ignored sigCHLD. I have a workaround -- in fact, I think the reason that sigCHLD was ignored was that there used to be a fork() call, but now that's gone. I'm no longer ignoring the signal, so it's not a problem for now.
I just recompiled a new version of 5.8.1 on my linux box and it still exhibits the same behavior. Oh, and I changed the parameter to system() to be './prog2.pl' with the same results. It looks like this account has a 'dot' in the $PATH. (bad, I know)
Here are the versions that I have tested:
linux 2.4.20-20.9 kernel (from RedHat9)
tested with both perl v5.8.0 and v5.8.1
using glibc 2.3.2 (glibc-2.3.2-27.9)
sun 5.8 Generic_108528-17 sun4u sparc SUNW, UltraSPARC-IIi-cEngine
perl v5.6.1
not sure how to tell the C library version on sun
FreeBSD 4.8-RELEASE
perl version 5.005_03
not sure how to tell the C library on FreeBSD
If you guys think I should submit a bug report, I'll definitely do that.
I haven't tested it, but I assume another workaround if someone really needed it would be to do the waitpid() inside of a reaper subroutine construct.
| [reply] [Watch: Dir/Any] |
|
The following piece of code examines the problem a bit further, along the guidelines of perlport:
#!/usr/bin/perl
use POSIX;
if(@ARGV){ $SIG{'CHLD'} = 'IGNORE'; }
system('./prog2.pl');
$status=$?;
if(WIFEXITED($status)){
print "prog2.pl exited normally, returning ",
WEXITSTATUS($status), "\n";
}elsif(WIFSIGNALED($status)){
print "prog2.pl was terminated with signal ",
WTERMSIG($status), "\n";
}elsif(WIFSTOPPED($status)){
print "prog2.pl is stopped for signal ",
WSTOPSIG($status), "\n";
}else{
print "can't understand what happened to prog2.pl; ",
"status is ",$status,"\n";
}
When I ran it under perl 5.8.0 (on i386 linux, kernel 2.4.20, glibc 2.3.2), I got the following results:
#./prog1.pl
prog2.pl exited normally, returning 5
#./prog1.pl ignore
prog2.pl was terminated with signal 127
Interesting enough, no POSIX signal has number 127, AFAIK...
something is not working here.
Ant9000
| [reply] [Watch: Dir/Any] [d/l] |
|
|
|
Yes, please do submit a bug report, using perlbug. Perlbug
will include the output of 'perl -V', and among this output
is the C library version number. Without a bug report, the
issue is unlikely to get fixed, unless you send in a patch
yourself.
I'm not able to reproduce this problem using Linux, kernel
2.4.18-something (for various somethings), glibc 2.2.5, and
Perl versions 5.005 .. 5.9.0.
Abigail
| [reply] [Watch: Dir/Any] |
Re: why does ignoring sigCHLD corrupt return value from system()?
by Abigail-II (Bishop) on Nov 05, 2003 at 00:24 UTC
|
I can't reproduce that with Linux, both with the signal
being ignored and not ignored. What versions of Perl are
you using, what kernel are you running, and which C library
are you using?
Abigail | [reply] [Watch: Dir/Any] |
Re: why does ignoring sigCHLD corrupt return value from system()?
by bfdi533 (Friar) on Nov 05, 2003 at 19:59 UTC
|
I have not been able to duplicate this "error".
I have tested this on Gentoo Linux (kernel 2.4.20, glibc 2.3.2) with Perl 5.8.0 and it returns 5 as intended.
Ed
| [reply] [Watch: Dir/Any] |
|
I ran into this on Gentoo with perl-5.20.2 with ithreads useflag enabled. Recompiling without ithreads (that is the default) fixed the problem.
| [reply] [Watch: Dir/Any] |
|
|