in reply to Re: Best way to handle readline errors?
in thread Best way to handle readline errors?

Firefly258, are you saying that perldoc readline is wrong? From perldoc readline:
for (;;) { undef $!; unless (defined( $line = <> )) { die $! if $!; last; # reached EOF } # ... }
That clearly indicates that EOF and a readline error can be distinguished by undefining $! before the call and then, if readline failed, checking if $! is set to non-0.

Replies are listed 'Best First'.
Re^3: Best way to handle readline errors?
by Firefly258 (Beadle) on Nov 18, 2006 at 13:50 UTC
    I should have said this before to make it a little clearer.

    Read the contents of $! to glean the exact cause of an error right after an unsuccessful operation, Do not test $! to determine the success of an operation, use the TRUE/FALSE value returned instead. The Menmonic of $! is -- "What just went bang?" not "Did I just hear bang?", There is an obvious difference.

    Your reading of the operation concerning $! is definitely right but the reading concerning the context in which it is done is not. Here, if <> returns undef to $line, defined returns FALSE to unless () which puts the execution control in its block, it is there and only there where $! is current and valid.

    E.g
    unless (defined( $line = <> )) { die $! if $!; # $! is only current and valid in the afterma +th of a failure last; # reached EOF }
    is not the same as
    $line = <>; if ($!) { print "Ohh noo, $!"; # an indefinite false-positive }
    if you should ask why?? Consider the following..
    $ touch test; # create the dummy $ perl -Mstrict -Wle 'undef $!; open my $fh, "<", "test" or warn "warn + : $!"; print "after : $!"' after : Inappropriate ioctl for device $ rm test; $perl -Mstrict -Wle 'undef $!; open my $fh, "<", "test" or warn "warn +: $!"; print "after : $!" warn : No such file or directory at -e line 1. after : No such file or directory
    In the first operation, open succeeds and returns a TRUE value so warn() is skipped. However in the second, open fails and returns FALSE, warn is triggered spitting out a valid $!. The $! outside the expression is not trustworthy as one would infer from the documentation of $! in perlvar.

    update

    a readline error can be distinguished by undefining $! before the call

    undefining $! is a useless, almost redundant operation IMO, consequetive operations will set $! if they need to, sometimes regardless of whether they succeed or fail.

    checking if $! is set to non-0

    It's more like, checking if $! is TRUE, because FALSE can be representation of not just 0 but undef, "" (blank) or "0";
      I don't think we're disagreeing on the use of $! only after a failure (i.e. only after a check of the result from readline for definedness).

      However, it's critical that $! be "emptied" (set to a FALSE value) before calling readline, if $! is to be used to distinguish between EOF and a read error, as the code from perldoc readline does.

        However, it's critical that $! be "emptied"

        It's not critical at all - I've already mentioned that undefining $! is a useless, almost redundant operation, consequetive operations will clear and set a previously set $! if they need to.

        As in the following example, "gobbledegook" is a non-existant file.
        $ perl -le 'open F, "gobbledegook" or print "WARN1: $!"; print "PRINT: + $!"; readlink "test" or print "WARN2: $!"; print "PRINT: $!' WARN1: No such file or directory PRINT: No such file or directory WARN2: Invalid argument PRINT: Invalid argument
        It's quite clear here that the currency or validity of $! after a system call is unaffected by it's previous state, it's just another global variable.

        I have reason to believe that some perl programmers undefine $! after a system call wherein they do not check or cannot check the return value or because $! wasn't localized during that operation. E.g. After a use; statement
        $ perl -e 'print "BANG: $!"' BANG: $ perl -Mstrict -e 'print "BANG: $!"' BANG: Bad file descriptor