ipc-system-simple icon indicating copy to clipboard operation
ipc-system-simple copied to clipboard

Avoid calling END{} blocks too many times

Open duelafn opened this issue 10 years ago • 3 comments

capturex will, if execution fails, call END{} blocks one too many times. Suggest adding this fix from http://stackoverflow.com/questions/4307482/how-do-i-disable-end-blocks-in-child-processes

duelafn avatar May 20 '15 04:05 duelafn

capturex will, if execution fails, call END{} blocks one too many times. Suggest adding this fix from http://stackoverflow.com/questions/4307482/how-do-i-disable-end-blocks-in-child-processes

Can you provide a code example that demonstrates the problem which your p.r. is intended to address?

Thank you very much. Jim Keenan (co-maintainer)

jkeenan avatar Jan 25 '20 02:01 jkeenan

I think that my original problem was an END{} block used by a GUI library being called prematurely. However, this example shows what can happen:

use strict;
use warnings;
use IPC::System::Simple qw/ capturex /;
use File::Path qw/ remove_tree /;

my $dir = "/tmp/t6LupMzfsF";
mkdir $dir;
END {
    print STDERR "FINISHED!\n";
    remove_tree $dir;
    # Log out of a website (invalidate LWP cookie)
    # Delete temporary directory
    # Use a GUI module that does cleanup in an END block
}

open my $F1, ">", "$dir/test.1" or die "Error writing $dir/test.1: $!";
print $F1 "Hello\n";
close $F1;

eval {
    capturex "/usr/bin/NO-SUCH-PROGRAM";
};

open my $F2, ">", "$dir/test.2" or die "Error writing $dir/test.2: $!";
print $F2 "Hello\n";
close $F2;

The END block is called in the forked child of capturex when in an eval. In this case, that child END block removes a temporary directory that the original process is still using. The result is that the open $F2 call fails since the directory is now gone.

Script output:

FINISHED!
Error writing /tmp/t6LupMzfsF/test.2: No such file or directory at /tmp/test.pl line 25.
FINISHED!

duelafn avatar Jan 31 '20 14:01 duelafn

Also, eval { capturex } with a failure is the only situation that causes an extra evaluation of END blocks. Other functions (capture, system, systemx) and successful capturex all behave correctly and do not evaluate END blocks multiple times. Therefore, there should be little concern of breaking existing code. It is unlikely that anyone is relying on calling END in the capturex child.

duelafn avatar Jan 31 '20 14:01 duelafn