Let me begin with a simplified script that produces strange behaiviour for me.

perl -we 'open $f, "<", "/etc/passwd" or die 1; for (0..2) { $! = 0; $ +l = readline $f; $s = $!; chomp $l; print qq/"$l", $s\n/; }'
Update: changed printf to print, which was a mistake and could cause problems if there were % signs in the file read.

This prints the following for me:

"root:x:0:0:root:/root:/bin/bash", Bad file descriptor "bin:x:1:1:bin:/bin:/bin/false", "daemon:x:2:2:daemon:/sbin:/bin/false",

Thus, readline succeeds as it should, but the first time I call it, it sets $! to EBADF.

It seems that this happens with any file, /etc/passwd is just an example. Also, it happens the first time I readline after a seek, not only after opening the file.

My questions are:

  1. Can any of you duplicate this problem? I am using perl, v5.8.2 built for i686-linux.
  2. Is it indeed readline that sets $!? Note that I've cleared $! before the readline, and I have not defined any signal handles here that could change $!, so I belive it is.
  3. Can readline report an error in $! and return a parital result instead of an undef? I guess no.
  4. Is readline (or any function for that matter) allowed to change $! if it succeeds? I think no. Although it's easy to make a mistake and forget to localize $!, but I think that libc and the perl core should behaive well in this sense. (Update: deleted libc. It shouldn't have much role here, as perlio does all the work.) Update: if it can set $! when it succeeds, can it do the same when it meets the end of file? If it could, I couldn't just do
    $! = 0; $line = <$file>; !defined($line) && $! and die "error";
    as perldoc perlfunc says, because that can report an error even if there isn't any. I'd have to use the eof function instead. Update: diotalevi says that eof() eof returns true after a read error, so one can't use that either. One could use IO::Handle::error, I'm not sure now if that's more reliable than $!.
  5. Summarizing, what does this error mean, and can I safely ignore it?

Update: I've tried the same code in a few other (un*x) machines, but I've only got the error with mine.


In reply to readline succeeds but sets $! = EBADF by ambrus

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.