Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Detecting write errors (disk full, bad media)

by Nyyr (Initiate)
on Jun 30, 2011 at 14:39 UTC ( [id://912190]=perlquestion: print w/replies, xml ) Need Help??

Nyyr has asked for the wisdom of the Perl Monks concerning the following question:

Hi there, I was googling about an hour for something like "perl print write error handling" but it seems that no one experienced (or thinked about possibility of) write errors. All error handling code I have found is about the open() function. What happens if:
open(my $filehandle, '>', 'C:\TEST.txt'); <--- OK print $filehandle "AAA\n"; <--- OK print $filehandle "BBB\n"; <--- OK print $filehandle "CCC\n"; <--- disk write error
How does PERL resp. PRINT FILEHANDLE function report such error? Does it return FALSE or UNDEF or does it throw an exception which has to be handled by:
eval { print $filehandle ....... } if ($@) { error hnadling }
??? Thanks :-)

Replies are listed 'Best First'.
Re: Detecting write errors (disk full, bad media)
by Corion (Patriarch) on Jun 30, 2011 at 14:43 UTC

    When you have a question about a function built into Perl, reading the documentation that comes with Perl for that function usually helps.

    > perldoc -f print Prints a string or a list of strings. Returns true if successful. ...

    So, if the print function does not return a true value, an error happened. Also see perlvar on $!.

      But who in the world checks the return value of print? Nobody, I guess, unless autodie handles it, if it can...

      I think a safer bet is to explicitly close the output filehandle and check its return value. Or, again, rely on autodie.

        Re. >>who in the world checks the return value of print?<< ... for the record, I do, IF it's writing a file likely to get very large. I didn't used to, then lost several hours of my life debugging strange behaviour in a production script which had worked fine for many months. The cause was a full disk, but the relevant print statements failed silently (even using strict and warnings) and the script happily ran to completion.
Re: Detecting write errors (disk full, bad media)
by kennethk (Abbot) on Jun 30, 2011 at 14:45 UTC
    I've never actually encountered this situation, but according to print,
    Returns true if successful.
    According to Perl error reporting convention (Error Variables) the method should set $!.
Re: Detecting write errors (disk full, bad media)
by toolic (Bishop) on Jun 30, 2011 at 15:00 UTC
    As others have pointed out, if print is not successful, the write to the file will not occur. By default, you will probably get no visible messages reporting the failure.

    However, if you use warnings, you will probably get a message to STDERR. I can not easily try the case where you have a full disk, but it is simple to try the case where you don't have permissions to write to a file.

    If you want to die when a print fails, you would need to add this code:

    print $filehandle "CCC\n" or die $!;
    Similarly, you could use autodie. UPDATE: As Anon correctly points out below, this can only be used for open/close, not print.

    I believe eval should work as you have shown. What happens when you try it?

      autodie does not work with core functions which cannot be overridden

      It will work with open/close, but not print

Re: Detecting write errors (disk full, bad media)
by ikegami (Patriarch) on Jun 30, 2011 at 17:03 UTC

    As per the documentation, print returns true on success and false on error, but errors aren't always detected immediately.

    When writing to a file,

    1. The data is (possibly) assembled in a buffer in Perl before being passed to the OS.
    2. The data is (possibly) assembled in a buffer in the OS before being being slated to be written to disk.
    3. The data is (likely) queued to be written to disk before actually being written to disk.

    An error in step 1 (e.g. the file handle isn't open) would result in print returns false.

    An error in step 2 might not result in print returning false. A subsequent write (e.g. print) or close will return false instead.

    An error in step 3 can occur after the file has already been closed, in which case it cannot be reported. On a unix system, one would use fsync(2) to ensure the data was written to disk correctly.

    $! will be set by print and close is they return false.

    Update: Greatly elaborated to clarify.

Re: Detecting write errors (disk full, bad media)
by aanriot (Sexton) on Jun 30, 2011 at 15:17 UTC

    And you can easily check this if you close the filehandle before printing "CCC".

    print $fh "CCC\n" or die "The file has vanished.";

    will returns something like "print() on closed filehandle $fh at ... line ... The file has vanished. at ... line ..."

Re: Detecting write errors (disk full, bad media)
by dcmertens (Scribe) on Jul 01, 2011 at 16:26 UTC
    I think the other monks have answered your question. BUT if you wanted to have the print statement croak when it encounters errors, you can override the standard output to go to a tied filehandle. Then operations that Perl would have sent to stdout go to your filehandle code. You could then have your filehandle code print its results to the old stdout, but check the return value for you. For details, see http://stackoverflow.com/questions/387702/how-can-i-hook-into-perls-print

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://912190]
Approved by kennethk
Front-paged by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2024-04-23 09:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found