|Keep It Simple, Stupid|
How do I make the garbage collector throw an exception when it fails to auto-close a filehandle?by Aristotle (Chancellor)
|on Jan 12, 2007 at 16:53 UTC||Need Help??|
Aristotle has asked for the
wisdom of the Perl Monks concerning the following question:
My basic scenario is like so:
Note that Iím not explicitly closing the filehandle. When execution leaves the subroutine (or loop or naked block or whichever kind of scope it is), the filehandle goes falls into limbo and is picked up by the garbage collector, which automatically closes the handle before disposing of the glob.
The problem is that close can actually fail (the canonical case is when there are write buffers left to flush but the disk has filled up). So therefore, you should always check the return value of close, at least on files you have opened for writing (whereas for files you have only opened for reading, there is very little point in caring). But when the garbage collector disposes of a filehandle, it ignores that return value. So I end up having to litter my code with explicit close calls anyway, just when I thought I could let the scope structure of the code implicitly define the scope of open files.
So I wonder if there is a way to get perl to throw an exception when it tries to close a filehandle in the garbage collector and gets an error. Most of the time, thatís what I want anyway, since there isnít much in the way of automatic recovery that can be done on failure to close a file, and the condition is usually indicative of some serious administrative issue, so the only sensible response is to die screaming bloody murder at the user.
In the simplest case, use Fatal qw( :void close ); would work for this, but I strongly doubt it, and in any case I canít think of a good way to purposefully trigger a close failure in order to test it.
(Note: in the chatterbox it was suggested to check $! just after the block, after clearing it just before the end of the block, but thatís really pretty pointless. For one thing, itís imprecise: there might be several filehandles or objects or tied variables going out of scope, any of which may set $!. Worse, though, it trades one line of manual cleanup code that can be placed within the block for several lines that need to be strewn across several scopes Ė so I wouldnít gain anything even if it worked in the first place.)
Makeshifts last the longest.