Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

DESTROY handler changes child exit status?

by saintmike (Vicar)
on May 09, 2013 at 07:04 UTC ( #1032733=perlquestion: print w/replies, xml ) Need Help??
saintmike has asked for the wisdom of the Perl Monks concerning the following question:

I was surprised to find that a DESTROY handler called when an object goes out of scope changes the exit status of the child process it's running in, even if that child exits with exit(exit_code).

This code:

package Foo; use strict; use warnings; sub new { bless {}, shift; } sub DESTROY { warn "$$: destroy"; system("waaaah"); } package main; use strict; use warnings; use POSIX ":sys_wait_h"; my $foo = Foo->new(); my $pid = fork(); die "fork failed" if !defined $pid; if( $pid ) { # parent print "$$: parent\n"; } else { # child print "$$: child\n"; # system("waaaah"); exit 5; } my $reaped = waitpid($pid, 0); my $child_exit_status = POSIX::WEXITSTATUS($?); print "pid=$reaped status: $child_exit_status\n";
shows
pid=4778 status: 255
although the child exits with exit(5). So the failing system() call in the DESTROY method of the object that goes out of scope overrides the explicitly set exit() value?

(If you comment out the system() call in the DESTROY handler and uncomment the one in the child code you'll get the expected exit code 5).

Surprised?

Replies are listed 'Best First'.
Re: DESTROY handler changes child exit status? (feature $?)
by Anonymous Monk on May 09, 2013 at 07:21 UTC
      Ha, I'm on win32, using  local $?; reveals a bug in the fork emulation, the effect is opposite of what it should be, using local $? should not cause $? to be used for exit value (which should be the default behavior)
      package Foo; use strict; use warnings; sub new { bless {}, shift; } sub DESTROY { warn "$$: destroy"; local $? if @ARGV; system("waaaah"); } package main; use strict; use warnings; use POSIX ":sys_wait_h"; my $foo = Foo->new(); my $pid = fork(); die "fork failed" if !defined $pid; if( $pid ) { # parent print "$$: parent\n"; } else { # child print "$$: child\n"; # system("waaaah"); exit 5; } my $reaped = waitpid($pid, 0); print "reaped( $reaped) \$?( $? ) >> 8 ( @{[ $? >> 8 ]} )\n"; #~ my $child_exit_status = POSIX::WEXITSTATUS($?); #~ print "pid=$reaped status: $child_exit_status\n"; __END__ $ perl fudge 2060: parent -3360: child -3360: destroy at fudge line 8. 'waaaah' is not recognized as an internal or external command, operable program or batch file. reaped( -3360) $?( 0 ) >> 8 ( 0 ) 2060: destroy at fudge line 8. 'waaaah' is not recognized as an internal or external command, operable program or batch file. $ perl fudge local 1628: parent -3804: child -3804: destroy at fudge line 8. 'waaaah' is not recognized as an internal or external command, operable program or batch file. reaped( -3804) $?( 1280 ) >> 8 ( 5 ) 1628: destroy at fudge line 8. 'waaaah' is not recognized as an internal or external command, operable program or batch file.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1032733]
Approved by marto
help
Chatterbox?
[Corion]: Hmmm... Weird. Maybe it needs that for doing its timers or something. Still weird.
[Corion]: But I guess I'll find out soonish, as my application seems to use Prima for more than just displaying the OpenGL output soonish ;))
[ambrus]: No, I think the timers are handled fine in the event loop, as far as I can see.
[Corion]: So far, I liked Prima quite well as it simply seems to do what I want even if it has an upside-down coordinate system. But it installs from CPAN out of the box and is cross-platform

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2016-12-09 10:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    On a regular basis, I'm most likely to spy upon:













    Results (150 votes). Check out past polls.