Over on perlmonks, I posed an as-yet answered problem regarding attempts 
to have a SIGINT handler delete a file that was part-way through being 
require()'d.

The problem seemed to be that perl still had the file open, although 
fileno($fh) was returning undef.  Likewise, any attempt to close($fh) 
the file before unlinking it (generally a requirement on Win32) fails, 
hence the unlink() itself fails.  See 
http://www.perlmonks.org/index.pl?node_id=394898 for more details.

I've now got closer to the problem by walking through things in a 
debugger, and it looks like perl does indeed have the file open, but has 
cleared the IoIFP() of the IO * concerned, hence fileno() and close() 
are useless.

This can be seen by running the following program and breaking in 
pp_require() when "name" is "reqtest.pl":

my $file = 'reqtest.pl';
my $fh;
open $fh, ">$file" or die "Can't create file '$file': $!: $^E\n";
print $fh "1;\n";
close $fh;
unshift @INC, sub {
    my($coderef, $filename) = @_;
    return unless $filename eq $file;
    open $fh, $filename or die "Can't read file '$file': $!: $^E\n";
    printf STDERR "Opened %s as fd %d\n", $filename, fileno($fh);
    return $fh;
};
require $file or die "require() failed\n";
unlink $file or die "Can't delete file '$file': $!: $^E\n";

Line 3164 in pp_ctl.c (in bleadperl) sets IoIFP(io) to Nullfp:

if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {
    PerlIO_close(IoOFP(io));
}
IoIFP(io) = Nullfp;
IoOFP(io) = Nullfp;

but (I think) "io" is the filehandle that my @INC coderef has just opened.

So now we seem to have exactly the situation that I thought was arising: 
perl has the "reqtest.pl" file open, but has thrown away its means of 
accessing it, preventing me from closing it before unlinking it.

Removing the IoIFP(io) = Nullfp line above fixes the problem, but now 
breaks t/op/inccode.t (only -- the rest of the test suite is OK).  The 
breakage can be reproduced in the above program by making the @INC 
coderef return a lexical from its own scope, rather than from the 
enclosing scope, e.g.

unshift @INC, sub {
    my($coderef, $filename) = @_;
    return unless $filename eq $file;
    open my $fh2, $filename or die "Can't read file '$file': $!: $^E\n";
    printf STDERR "Opened %s as fd %d\n", $filename, fileno($fh2);
    return $fh2;
};

Why does not clearing IoIFP() cause this to break?

- Steve



------------------------------------------------
Radan Computational Ltd.

The information contained in this message and any files transmitted with it are 
confidential and intended for the addressee(s) only.  If you have received this 
message in error or there are any problems, please notify the sender immediately.  The 
unauthorized use, disclosure, copying or alteration of this message is strictly 
forbidden.  Note that any views or opinions presented in this email are solely those 
of the author and do not necessarily represent those of Radan Computational Ltd.  The 
recipient(s) of this message should check it and any attached files for viruses: Radan 
Computational will accept no liability for any damage caused by any virus transmitted 
by this email.

Reply via email to