Subject: | Subprocess created using safe pipes wipes out temp files |
perl 5.14.2, CGI 3.52
If a short-lived subprocess is created using safe pipes after a CGI instance has already been created, the cleanup of the subprocess will demolish the tempfiles used by the parent. Here's a short script (arghno.pl) that demonstrates the problem:
#!/usr/bin/perl
use strict;
use CGI;
use CGI::Carp ('fatalsToBrowser');
my $q = new CGI;
print CGI::header();
my $fn = $q->param('filepath');
my $f = $q->tmpFileName($fn);
my $handle;
my $pid = open($handle, "-|");
if ($pid) {
print "This is the parent";
die "Parent: Tmpfile has gone before reading!" unless -e $f;
my $data = <$handle>;
die "Parent: Tmpfile has gone after reading!" unless -e $f;
} else {
# This is the child
print "This is the child";
}
Invoke with the following HTML:
<html>
<body>
<form enctype="multipart/form-data" action="arghno.pl" method="post">
<input type="file" name="filepath" value="" />
<input type="submit" value='Upload file' />
</form>
</body>
</html>
The temp files are removed in the CGITempFile::DESTROY method, when it is invoked during subprocess cleanup. Curiously enough the problem is not seen when using fork() to create the subprocess.
I was able to work around this problem by monkey-patching CGITempFile::DESTROY so that it was only invoked when called from the parent process, thus:
our $CONSTRUCTOR_PID = $$;
our $SAVE_DESTROY = \&CGITempFile::DESTROY;
if ( defined $SAVE_DESTROY ) {
no warnings 'redefine';
*CGITempFile::DESTROY = sub {
if ( $$ == $CONSTRUCTOR_PID ) {
# Parent process, unlink the temp file
&$SAVE_DESTROY(@_);
}
};
}
my $query - new CGI();
etc.