in reply to Best way to handle readline errors?

I did some digging (on Windows XP, using perl 5.8.8). I didn't come up with a solution, but I thought I'd post what I found out.

In all cases, I can confirm an IO error occured, since the OS pops a dialog asking to reinsert the disk once all read buffers have been emptied.

Test programs:

For <$fh>:

use strict; use warnings; my $file_name = 'G:\\I386\\DRIVER.CAB'; # 50MB file. open(my $fh, '<', $file_name) or die("Unable to open file \"$file_name\": $!\n"); # Read 100 bytes at a time. #binmode($fh); #$/ = \100; my $line; undef $!; $line = <$fh>; my $ok_defined = defined($!); my $ok_str_val = "$!"; my $ok_num_val = 0+$!; print("Eject the media then press Enter."); <STDIN>; undef $!; for (;;) { undef $!; last if not defined ($line = <$fh>); warn(length($line), "\n"); } my $bad_defined = defined($!); my $bad_str_val = "$!"; my $bad_num_val = 0+$!; close($fh) or warn("Unable to read file \"$file_name\": $!\n"); print("On success, "); if ($ok_defined) { print("\$! = \"$ok_str_val\"/$ok_num_val\n"); } else { print("\$! is not defined\n"); } print("On failure, "); if ($bad_defined) { print("\$! = \"$bad_str_val\"/$bad_num_val\n"); } else { print("\$! is not defined\n"); }

For sysread and read:

use strict; use warnings; my $file_name = 'G:\\I386\\DRIVER.CAB'; # 50MB file. open(my $fh, '<', $file_name) or die("Unable to open file \"$file_name\": $!\n"); my $buf; my $rv; $rv = sysread($fh, $buf='', 1); print("On success, "); if (defined($rv)) { print("\$rv = $rv\n"); } else { print("\$rv is not defined\n"); } print("Eject the media then press Enter."); <STDIN>; 1 while $rv = sysread($fh, $buf='', 1); print("On failure, "); if (defined($rv)) { print("\$rv = $rv\n"); } else { print("\$rv is not defined\n"); } close($fh) or warn("Unable to read file \"$file_name\": $!\n");

Replies are listed 'Best First'.
Re^2: Best way to handle readline errors?
by jrw (Monk) on Nov 11, 2006 at 21:59 UTC
    ikegami, I liked your approach (ejecting a CD to cause a read error). So, here are my results which are somewhat different than yours:
    • All three versions read 99Mb after the disk was ejected, indicating that WinXP must be caching the CD file
    • sysread returned undef but $! was set to 0!
    • Failures in sysread and readline did not cause close to fail whereas read failure did.
    • In my tests, readline did fail, similar to read, as expected.
    The results, run on WinXP cygwin using ActiveState Perl for Windows v5.8.7: Here are the results when I set $initial_read to 0: Here's my test code:

      All three versions read 99Mb after the disk was ejected, indicating that WinXP must be caching the CD file

      It did that to me when I used Alcohol to mount and unmount a virtual CD instead of ejecting a real CD. Apparently, Alcohol doesn't fully unmount an image with an open file handle.

      When I switched to using a real CD, WinXP would prompt me to reinsert the disk when all cached data had been read. When I Cancel that dialog, Perl returns an error.

      So, can anyone help with my original question? I'm sure I'm not the only perl person who is concerned with thorough error handling in code where error handling is important (such as code run by root).

      The original question was: what is the Perl Best Practice idiom for handling readline errors?

      Being a new poster to PerlMonks, but not a new perl user, is there anything I can do or any way I can help to get this question answered? Anything I can do to get more attention focused on this question?

Re^2: Best way to handle readline errors?
by jrw (Monk) on Nov 11, 2006 at 14:49 UTC
    Thanks, ikegami! That was useful.

    It's worrying that <$fh> won't return when you eject and/or reinsert the media. What's going on down in the bowels of that code?

    sysread and read were planned in a way which takes errors into consideration (patterned after read in c). But error handling in readline seems to be somewhat of an afterthought. It makes me wonder if I have to reimplement readline at the perl level using read (Ugh!).

    I started asking this question because it's hard for me to justify writing code which will run as root that doesn't have complete error checking, including checking for input errors. Oh, Damian, why didn't Perl Best Practices should us lowly monks how to handle readline errors, too?