$SIG{CHLD} and system

H

Heinrich Mislik

perl -e '$SIG{CHLD} = "IGNORE";system("date") and die'

gives me

Thu Sep 30 14:34:22 MSZ 2004
Died at -e line 1.

I can understand, why this happens. But is it documented? Shouldn't system
set up it's own signalhandlers? The function system in C does so. Does this mean, that perl does not call this function?

Any thoughts


Cheers
 
K

kspecial

perl -e '$SIG{CHLD} = "IGNORE";system("date") and die'
gives me

Thu Sep 30 14:34:22 MSZ 2004
Died at -e line 1.

That's exactly what it's supposed to give you...
I can understand, why this happens.

Why what happens? Perl run's "date", then returns when date exits,
after which it proceeds to die....perl is reporting that it die()ed.
I'm not sure what you expected to happen. You can check return values
etc of the system():

$exit_value = $? >> 8;
$signal_num = $? & 127
$dumped_core = $? & 128

--K-sPecial
 
H

Heinrich Mislik

Mostly one thought: read "perldoc -f system". It forks a child
and, in cases like yours when there's no meta chars in
the argument string, calls execvp. No system() call invoked.

Right. But even with this its the same:

perl -e '$SIG{CHLD} = "IGNORE";system("date 2>/dev/null") and die'

Fri Oct 1 11:43:48 MSZ 2004
Died at -e line 1.
Apart from that, I can't reproduce this behaviour
(just tested 5.6.1 and 5.8.[03] on Linux and Win32).
%SIG isn't changed by the call of system("date").

Just to clarify: my point is, that the returncode of system is changed by setting $SIG{CHLD} = "IGNORE".
What version and OS are you on?

I tried

This is perl, v5.8.4 built for aix

This is perl, v5.6.1 built for i386-freebsd

This is perl, v5.8.2 built for cygwin-thread-multi-64int

cygwin is a bit different with the last examle (with the 2>/dev/null):
sh gets into an enless loop. This seems to be a problem with cygwin's
C-function system.

Cheers
 
H

Heinrich Mislik

That's exactly what it's supposed to give you...


Why what happens? Perl run's "date", then returns when date exits,
after which it proceeds to die....perl is reporting that it die()ed.
I'm not sure what you expected to happen. You can check return values
etc of the system():

I expected to get the sam result for

perl -e '$SIG{CHLD} = "IGNORE";system("date") and die $?'

which prints

Fri Oct 1 12:08:04 MSZ 2004
-1 at -e line 1.

and

perl -e '$SIG{CHLD} = "DEFAULT";system("date") and die $?'

which prints

Fri Oct 1 12:09:12 MSZ 2004
 
J

Joe Smith

Why what happens? Perl run's "date", then returns when date exits,
after which it proceeds to die....perl is reporting that it die()ed.
I'm not sure what you expected to happen.

He was expecting the value returned by system() to be the same
as what gets stored in $? (zero on success, nonzero on failue).
But that is no longer the case; system() is returning -1 regardless
of the command's exit code.

solaris% perl -le '$SIG{CHLD} = "DEFAULT";print(system("/bin/true"))'
0
solaris% perl -le '$SIG{CHLD} = "DEFAULT";print(system("/bin/false"))'
65280
solaris% perl -le '$SIG{CHLD} = "IGNORE";print(system("/bin/true"))'
-1
solaris% perl -le '$SIG{CHLD} = "IGNORE";print(system("/bin/false"))'
-1

This behavior is not explictly documented; you have to do some digging
to see why the return value if system() has become misleading or useless.

From 'perldoc -f system':

The return value is the exit status of the program as returned
by the "wait" call. To get the actual exit value shift right
by eight (see below). Return value of -1 indicates a failure
to start the program (inspect $! for the reason).

From 'perldoc perlvar':

Using a value of 'IGNORE' usually has the effect of
ignoring the signal, except for the "CHLD" signal.
See perlipc for more about this special case.

From 'perldoc perlipc':

On most Unix platforms, the "CHLD" (sometimes also known as
"CLD") signal has special behavior with respect to a value
of 'IGNORE'. Setting $SIG{CHLD} to 'IGNORE' on such a
platform has the effect of not creating zombie processes
when the parent process fails to "wait()" on its child
processes (i.e. child processes are automatically reaped).
Calling "wait()" with $SIG{CHLD} set to 'IGNORE' usually
returns "-1" on such platforms.

That means that 'perldoc -f system' should have said:

The return value is what is returned by the "wait" call,
which the program's exit status. (Except when $SIG{CHLD}
is set to 'IGNORE', in which case system() returns -1.)

Conclusion: If it is possible that your program will be running with
a non-default value of $SIG{CHLD}, you'll have to change your
program logic to not look at the return value from system().
Change
system($command) and die;
to
system($command); $? and die;


-Joe
 
H

Heinrich Mislik

Conclusion: If it is possible that your program will be running with
a non-default value of $SIG{CHLD}, you'll have to change your
program logic to not look at the return value from system().
Change
system($command) and die;
to
system($command); $? and die;

Won't work either. $SIG{CHLD} = "IGNORE" really means "i'm not interessted
in the return the value from my childs". Since no zombie will be created,
there is no way, get the return value.

OTH, if system temporary changes $SIG{CHLD} and any other child exits
during the system function does waitpid, there would remain an unwanted
zombie.

perdoc -f system should make this clear.

cheers
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top