http://qs1969.pair.com?node_id=485235

eff_i_g has asked for the wisdom of the Perl Monks concerning the following question:

monks,

i am working with fork, %SIG, and the END block on version 5.8.6, and i have a few curiosities:

  1. when exit is used, is a SIG called (i tried INT and QUIT) or only the END block?
  2. what happens when you use exit inside of a terminating signal subroutine? it knows it is already exiting, so is exit ignored, or will it still use the return value specified, if any?
  3. when working with fork, can you "instruct" code within an END block to only execute for the parent and not the child?

thank you.

edit: sorry for the name botch on the reply etm, i just got back from lunch :P

Replies are listed 'Best First'.
Re: fork, %SIG, END.
by etm117 (Pilgrim) on Aug 19, 2005 at 17:57 UTC
    First off, these are from my experiences trying the same thing, they may not be the best answers, but they do work for me.

    1. END block.

    2. To make sure you still exit with the return value that got you into the END block, make sure to put local $?; at the beginning of your end block.

    If you don't do this, the return value of the last thing you do in the end block will be the return value back to the caller of the script (which for me is Autosys and it was causing a script that should have been returning failure to return success because my last statement was a successful print to STDERR that my script was returning failure.

    3. The way I accomplished this was in my parent to have a my $_PARENT_PID = $$; as a global variable. Then in the END block, you can check:

    if( $$ == $_PARENT_PID ) { # parent } else { # child }

    Like I said, not the best way, but it worked. Maybe someone else will have some better solutions.

    best of luck...

      etm1777:

      it is my understanding that the program does not exit within the END block, but after the END block has completed; the scope returns to a global (file) one, where $? is then returned, like so:
      END { local $?; # preserve previous return code # do anything } # now, outside of the END block, # $? refers to the global and the # program officially terminates # using this value.
        I agree with that code block and think we are speaking towards the same thing. I use the local $? in my END block to preserve the exit code also.

        I think I brought it up as an heads up because that bit me in the butt when I first started using the END block, I wasn't preserving the $? and therefore code inside the END block was causing it to be modified and the script not exiting with the value I wanted.

Re: fork, %SIG, END.
by Ven'Tatsu (Deacon) on Aug 19, 2005 at 18:15 UTC
    1. exit does not create a signal so nothing in %SIG will be called.
    2. Inside a signal handler exit should behave similar to when called elsewhere, as it is possible for most signal handlers to choose not to exit they need to either exit or die themselves.
      Under *nix try (press ctrl+c 5 times to exit)
      perl -e 'my $ccc = 0; $SIG{INT} = sub { $ccc++; print "^C pressed $ccc + times\n"; exit 42 if $ccc >= 5 }; 1 while 1;'; echo $?
    3. One way is to set a flag right after the fork based on what side of the fork you are on.
      my $parentFlag; my $pid = fork(); if ($pid) { #parent process $parentFlag= 1; } elsif (defined $pid) { #child process $parentFlag= 0; } else { #error on fork die "some useful message: $!\n"; } END { if ($parentFlag) { #parent end code } elsif (defined $parentFlag) { #child end code } else { #end block after failed fork or exit before the fork? } }