mob mob - 3 months ago 9
Perl Question

How do I disable END blocks in child processes?

I frequently use

fork
in programs that also have
END { ... }
blocks:

...
END { &some_cleanup_code }
...
my $pid = fork();
if (defined($pid) && $pid==0) {
&run_child_code;
exit 0;
}


The child process executes the
END {}
block as it is exiting, but usually I don't want that to happen. Is there a way to prevent a child process from calling the
END
block at exit? Barring that, is there a way for a program to "know" that it is a child process, so I could say something like

END { unless (i_am_a_child_process()) { &some_cleanup_code } }


?

Answer
use B;
@{; eval { B::end_av->object_2svref } || [] } = ();

I thought there was a Devel:: module that also let you do this, but I can't find it now.

Of course, you can't safely do this if you are using arbitrary modules that might be using END blocks for their own purposes...


(edit by OP) You can get control over the END blocks with B::end_av. As a proof-of-concept:

END { print "This is the first end block.\n"; }
my $END_block_2_line = __LINE__ + 1;
END { print "This is the second end block.\n"; }
END { print "This is the third end block.\n" }

sub disable_specific_END_block {
  use B;
  my ($file, $line) = @_;
  eval {
    my @ENDs = B::end_av->ARRAY;
    for (my $i=$#ENDs; $i>=0; $i--) {
      my $cv = $ENDs[$i];
      if ($cv->START->file eq $file && $cv->START->line == $line) {
        splice @{B::end_av->object_2svref}, $i, 1;
      }
    }
  };
}

disable_specific_END_block(__FILE__, $END_block_2_line);


$ perl endblocks.pl
This is the third end block.
This is the first end block.

Usually something like this would be overkill for what I need, but I can see some cases where this would come in handy.