Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

readline: sets $! even if no error occured #8289

Closed
p5pRT opened this issue Jan 20, 2006 · 11 comments
Closed

readline: sets $! even if no error occured #8289

p5pRT opened this issue Jan 20, 2006 · 11 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 20, 2006

Migrated from rt.perl.org#38285 (status was 'rejected')

Searchable as RT38285$

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2006

From Nikolaus@rath.org

Created by Nikolaus@rath.org

This is a bug report for perl from Nikolaus@​rath.org,
generated with the help of perlbug 1.35 running under perl v5.8.7.

-----------------------------------------------------------------

Apparently, readline sets $! to "invalid filedescriptor" even if no
error occured​:

[0] nokile​:~/Work$ cat perlbug2.pl
#!/usr/bin/perl

# Overload IO​::File to die on errors
package IO​::File​::Fatal;
use strict;
use warnings;
use IO​::File;
use base 'IO​::File';

sub getline {
  my $this = shift;
  undef $!;
  my $ret = readline($this);
  warn "got line '$ret'\n"; # for debugging
  die $! if $!;
  return $ret;
}

######## MAIN PROGRAM ##########
package main;
use strict;
use warnings;

my $fh = new IO​::File​::Fatal(shift(), "<");
print $fh->getline();

[0] nokile​:~/Work$ echo "Just one line" > data

[0] nokile​:~/Work$ ./perlbug2.pl data
got line 'Just one line
'
Bad file descriptor at ./perlbug2.pl line 15, <GEN0> line 1.

[9] nokile​:~/Work$

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl v5.8.7:

Configured by Debian Project at Mon Dec 12 13:59:01 UTC 2005.

Summary of my perl5 (revision 5 version 8 subversion 7) configuration:
  Platform:
    osname=linux, osvers=2.6.10, archname=i486-linux-gnu-thread-multi
    uname='linux rothera 2.6.10 #1 smp fri may 13 09:24:22 utc 2005 i686 gnulinux '
    config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i486-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.7 -Dsitearch=/usr/local/lib/perl/5.8.7 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.7 -Dd_dosuid -des'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include'
    ccversion='', gccversion='4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
    perllibs=-ldl -lm -lpthread -lc -lcrypt
    libc=/lib/libc-2.3.5.so, so=so, useshrplib=true, libperl=libperl.so.5.8.7
    gnulibc_version='2.3.5'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    SPRINTF0 - fixes for sprintf formatting issues - CVE-2005-3962


@INC for perl v5.8.7:
    /etc/perl
    /usr/local/lib/perl/5.8.7
    /usr/local/share/perl/5.8.7
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.8
    /usr/share/perl/5.8
    /usr/local/lib/site_perl/i486-linux-gnu-thread-multi
    /usr/local/lib/site_perl
    .


Environment for perl v5.8.7:
    HOME=/home/nikratio
    LANG=en_US.UTF-8
    LANGUAGE (unset)
    LC_ADDRESS=de_DE.UTF-8
    LC_COLLATE=de_DE.UTF-8
    LC_CTYPE=de_DE.UTF-8
    LC_IDENTIFICATION=en_US.UTF-8
    LC_MEASUREMENT=de_DE.UTF-8
    LC_MESSAGES=en_US.UTF-8
    LC_MONETARY=de_DE.UTF-8
    LC_NAME=de_DE.UTF-8
    LC_NUMERIC=de_DE.UTF-8
    LC_PAPER=de_DE.UTF-8
    LC_TELEPHONE=de_DE.UTF-8
    LC_TIME=de_DE.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=~/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11
    PERL_BADLANG (unset)
    PERL_UNICODE=SDAL
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jan 20, 2006

From eric-amick@comcast.net

[nikratio - Fri Jan 20 02​:32​:39 2006]​:

This is a bug report for perl from Nikolaus@​rath.org,
generated with the help of perlbug 1.35 running under perl v5.8.7.

-----------------------------------------------------------------

Apparently, readline sets $! to "invalid filedescriptor" even if no
error occured​:

[0] nokile​:~/Work$ cat perlbug2.pl
#!/usr/bin/perl

# Overload IO​::File to die on errors
package IO​::File​::Fatal;
use strict;
use warnings;
use IO​::File;
use base 'IO​::File';

sub getline {
my $this = shift;
undef $!;
my $ret = readline($this);
warn "got line '$ret'\n"; # for debugging
die $! if $!;
return $ret;
}

######## MAIN PROGRAM ##########
package main;
use strict;
use warnings;

my $fh = new IO​::File​::Fatal(shift(), "<");
print $fh->getline();

[0] nokile​:~/Work$ echo "Just one line" > data

[0] nokile​:~/Work$ ./perlbug2.pl data
got line 'Just one line
'
Bad file descriptor at ./perlbug2.pl line 15, <GEN0> line 1.

[9] nokile​:~/Work$

From the entry for $! in perlvar​:

This means that the value of $! is meaningful only *immediately* after a
*failure* [emphasis in original]

The readline was successful, so you shouldn't be checking $!. Not a bug.

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2006

From @tamias

On Fri, Jan 20, 2006 at 12​:46​:34PM -0800, Eric Amick via RT wrote​:

[nikratio - Fri Jan 20 02​:32​:39 2006]​:

sub getline {
my $this = shift;
undef $!;
my $ret = readline($this);
warn "got line '$ret'\n"; # for debugging
die $! if $!;
return $ret;
}

From the entry for $! in perlvar​:

This means that the value of $! is meaningful only *immediately* after a
*failure* [emphasis in original]

The readline was successful, so you shouldn't be checking $!. Not a bug.

However, from the entry for readline​:

  If readline encounters an operating system error, $! will be
  set with the corresponding error message. It can be helpful
  to check $! when you are reading from filehandles you don't
  trust, such as a tty or a socket. The following example
  uses the operator form of "readline", and takes the
  necessary steps to ensure that "readline" was successful.

  for (;;) {
  undef $!;
  unless (defined( $line = <> )) {
  die $! if $!;
  last; # reached EOF
  }
  # ...
  }

I think this example is in error.

Ronald

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2006

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jan 21, 2006

From @demerphq

On 1/21/06, Ronald J Kimball <rjk-perl-p5p@​tamias.net> wrote​:

On Fri, Jan 20, 2006 at 12​:46​:34PM -0800, Eric Amick via RT wrote​:

[nikratio - Fri Jan 20 02​:32​:39 2006]​:

sub getline {
my $this = shift;
undef $!;
my $ret = readline($this);
warn "got line '$ret'\n"; # for debugging
die $! if $!;
return $ret;
}

From the entry for $! in perlvar​:

This means that the value of $! is meaningful only *immediately* after a
*failure* [emphasis in original]

The readline was successful, so you shouldn't be checking $!. Not a bug.

However, from the entry for readline​:

If readline encounters an operating system error\, $\! will be
set with the corresponding error message\.  It can be helpful
to check $\! when you are reading from filehandles you don't
trust\, such as a tty or a socket\.  The following example
uses the operator form of "readline"\, and takes the
necessary steps to ensure that "readline" was successful\.

    for \(;;\) \{
        undef $\!;
        unless \(defined\( $line = \<> \)\) \{
            die $\! if $\!;
            last; \# reached EOF
        \}
        \# \.\.\.
    \}

I think this example is in error.

Why?

Note the difference between the example and the op. One undef's $!
before reading and then then immediately after checks $! but only if
the result is undefined. The other checks $! every time but after a
warn, which itself could set $!.

IMO the op should have said​:

sub getline {
  my $this = shift;
  undef $!;
  my $ret = readline($this);
  die $!
  if ! defined( $ret ) &amp;&amp; $!; # must happen before anything else
  return if ! defined( $ret );
  warn "got line '$ret'\n"; # for debugging
  return $ret;
}

Cheers,
yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Jan 27, 2006

From Nikolaus@rath.org

Apparently, readline sets $! to "invalid filedescriptor" even if no
error occured​:

sub getline {
my $this = shift;
undef $!;
my $ret = readline($this);
warn "got line '$ret'\n"; # for debugging
die $! if $!;
return $ret;
}

The readline was successful, so you shouldn't be checking $!. Not a bug.

So how do I know whether readline was successful if I can't check $!? An
undef might just be eof and no error.

Apart from that, perldoc -f readline recommends checking $!.

@p5pRT
Copy link
Author

p5pRT commented Jan 27, 2006

From Nikolaus@rath.org

Note the difference between the example and the op. One undef's $!
before reading and then then immediately after checks $! but only if
the result is undefined. The other checks $! every time but after a
warn, which itself could set $!.

Well, I inserted warn() only after discovering the problem. Checking $!
only if the readline return value is undef actually circumvents the problem.

However, I still consider the current behaviour a bug. Is there any
reason for setting $! if no error occured?

@p5pRT
Copy link
Author

p5pRT commented May 3, 2006

From Mark.Martinec@ijs.si

however, I still consider the current behaviour a bug.
Is there any reason for setting $! if no error occured?

It is not a bug, this follows the same principle as all system
calls in Unix follow​: if a status returned from a system
routine indicates and error, then errno contains an error
description. If status does not indicate an error, then
errno is undefined - it may contain any value. There is
no guarantee that it is 0 or that its old value is retained.

IMO, this ticket should be closed as 'not a bug'.

Btw, there is a similar bug report #39060, but that one
is genuine, and is not to be confused with this one.

  Mark

@p5pRT
Copy link
Author

p5pRT commented May 26, 2009

From skasal@redhat.com

On Wed May 03 08​:15​:10 2006, mmartinec wrote​:

IMO, this ticket should be closed as 'not a bug'.

I reviewed this and I agree with the reasoning. So I'm trying to close
this.

@p5pRT
Copy link
Author

p5pRT commented May 26, 2009

@nwc10 - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this as completed Jun 2, 2009
@p5pRT
Copy link
Author

p5pRT commented Jun 2, 2009

skasal@redhat.com - Status changed from 'resolved' to 'rejected'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant