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.
