Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^2: How do I make the garbage collector throw an exception when it fails to auto-close a filehandle?

by Aristotle (Chancellor)
on Jan 13, 2007 at 07:25 UTC ( #594505=note: print w/ replies, xml ) Need Help??


in reply to Re: How do I make the garbage collector throw an exception when it fails to auto-close a filehandle?
in thread How do I make the garbage collector throw an exception when it fails to auto-close a filehandle?

That was my next thought about attacking the problem. Iíd prefer being able to enable my desired behaviour with some sort of pragma somewhere and then not have to do anything special in the affected code, though. If I have to do any extra work at all (and if itís just remembering to instantiate a particular IO class instead of just calling open), Iíd rather stick to doing dumb and simple extra work than adding insufficiently magic complexity to the code.

Makeshifts last the longest.


Comment on Re^2: How do I make the garbage collector throw an exception when it fails to auto-close a filehandle?
Re^3: How do I make the garbage collector throw an exception when it fails to auto-close a filehandle?
by diotalevi (Canon) on Jan 13, 2007 at 16:26 UTC

    The following triggers IO::Handle::DESTROY. It does not trigger IO::File::DESTROY even though this is a file handle.

    use IO::Handle; # or IO::File *IO::Handle::DESTROY { print "here\n" } { open my $fh, '<', 'a-file' or die; }

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      That seems to be the only reliable approach. You donít even need to load IO::Handle. However, I canít actually get it to complain:

      use strict; sub IO::Handle::DESTROY { my $self = shift; warn +(caller 0)[3]."($self)\n"; close $self or die "$!\n"; } { if( open my $fh, ">", "/dev/full" ) { print { $fh } 1 } } warn "Terminating\n"; __END__ IO::Handle::DESTROY(IO::Handle=IO(0x8130c0c)) Terminating

      The error does occur: if I change the die to a warn, I see the warning. But while die aborts execution (statements after it will not run), I canít make it throw an exception. The conditions from Carping in DESTROY, which was mentioned in another subthread, do not apply either.

      Makeshifts last the longest.

        die() doesn't work, but exit() still does. I tried this, with good results:
        #!/usr/bin/perl use strict; use warnings; $| = 1; sub IO::Handle::DESTROY { print "desctructor enter\n"; my $self = shift; close $self or do { warn $!; exit; }; print "destructor exit\n"; } sub something { open ( my $foo, '>', '/dev/full' ); print $foo 'bar'; } print "pre\n"; something(); print "post\n";
        You can, of course, adjust the arguments list to make exit() return a failure code to the OS. Unfortunately, that's not going to get caught as an exception, though.

        This leaves some possibilities, although none are spectacular if you were counting on catching the die(). You could certainly set a flag before the exit and have final clean-up triggered by an END block if that flag is set. You could call the cleanup right from there in the destructor and exit from the cleanup code. If there's ever a reason not to leave the program on the full disk error, you could trigger your complaining/cleanup code in there and continue.

        Depending on how much state you want to handle, you can work around the die getting caught lots of ways. Here's one that works in toy testing, and lets you use it as a module:
        package Foo; my $error; END { warn $error if $error; } sub IO::Handle::DESTROY { print "desctructor enter\n"; my $self = shift; close $self || do { $error = $!; exit; }; print "destructor exit\n"; } 1;
        You can make the END block do whatever you need it to do to complain/cleanup. Just put use Foo; at the top of your program, and any failed file close triggers exit and what ever's in your END block. For that matter, since setting IO::Handle::DESTROY in the module seems to work pretty well, you could just put your cleanup code in there, too.


        Christopher E. Stith

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://594505]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (15)
As of 2014-07-30 20:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (240 votes), past polls