Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid calling END{} blocks too many times #16

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

duelafn
Copy link

@duelafn duelafn commented May 20, 2015

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

@jkeenan
Copy link
Collaborator

jkeenan commented Jan 25, 2020

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)

@duelafn
Copy link
Author

duelafn commented Jan 31, 2020

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
Copy link
Author

duelafn commented Jan 31, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants