Bug 221113 - readline function in perl does not correctly set $!
Summary: readline function in perl does not correctly set $!
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: perl
Version: rawhide
Hardware: i386
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Stepan Kasal
QA Contact: David Lawrence
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2007-01-01 23:46 UTC by Wojciech Pilorz
Modified: 2009-06-03 18:50 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Enhancement
Doc Text:
Clone Of:
Environment:
Last Closed: 2009-06-03 18:50:49 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)
readline_test.pl test script (1.37 KB, application/x-perl)
2007-01-01 23:46 UTC, Wojciech Pilorz
no flags Details
readline_test.bash run readline_test.pl 16 times with different settings and data (281 bytes, text/plain)
2007-01-01 23:48 UTC, Wojciech Pilorz
no flags Details
how to test I/O errors and readline behaviour (1.73 KB, text/plain)
2007-01-02 00:32 UTC, Wojciech Pilorz
no flags Details

Description Wojciech Pilorz 2007-01-01 23:46:05 UTC
Description of problem:

perldoc -f readline

displays example code how do check for errors with readline:
for (;;) {
    undef $!;
    unless (defined( $line = <> )) {
        die $! if $!;
        last; # reached EOF
    }
    # ...
}

Unfortunately this method no longer works as described in current perl version.

I am including a short perl script readline_test.pl attempting to use that
method and bash script readline_test.bash calling that perl script 16 times;
input is either "1234" or "1234\n",
PERLIO environment variable is set to perlio or stdio,
(PERLIO=perlio is equivalent to PERLIO not set in FC6)
$/ is set to undef, not modified, \2, \1024.

$/ is set to a reference to value specified in environment variable CHUNKSIZE,
unless it is 0 ($/ not set in this case) or negative ($/ set to undef).

In correct perl implementation all 16 tests should run successfully (no die).

The results included show that PERLIO=stdio is better (4 tests fail for stdio, 6
tests fail for perlio)

Version-Release number of selected component (if applicable):
perl-5.8.8-10

How reproducible:
always

Steps to Reproduce:
1. save readline_test.pl and readline_test.bash files from attachemnts into
current directory
2. run the following command in the current directory
  bash readline_test.bash
you could prefer to run 
  bash -vx readline_test.bash
to see exactly what is being run

  
Actual results:

$ bash readline_test.bash
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=-1,PERLIO=perlio...
 INFO: $/ will be set to undef
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=-1,PERLIO=stdio...
 INFO: $/ will be set to undef
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=0,PERLIO=perlio...
 INFO: $/ will not be set
Bad file descriptor at readline_test.pl line 30, <F> line 1.
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=0,PERLIO=stdio...
 INFO: $/ will not be set
Bad file descriptor at readline_test.pl line 30, <F> line 1.
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=2,PERLIO=perlio...
 INFO: $/ will be set to 2
 INFO: File /dev/stdin has been read, nbytes = 4
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=2,PERLIO=stdio...
 INFO: $/ will be set to 2
 INFO: File /dev/stdin has been read, nbytes = 4
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=1k,PERLIO=perlio...
 INFO: $/ will be set to 1024
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=1k,PERLIO=stdio...
 INFO: $/ will be set to 1024
 INFO: File /dev/stdin has been read, nbytes = 4
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=-1,PERLIO=perlio...
 INFO: $/ will be set to undef
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=-1,PERLIO=stdio...
 INFO: $/ will be set to undef
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=0,PERLIO=perlio...
 INFO: $/ will not be set
 INFO: File /dev/stdin has been read, nbytes = 5
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=0,PERLIO=stdio...
 INFO: $/ will not be set
Bad file descriptor at readline_test.pl line 30, <F> line 1.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=2,PERLIO=perlio...
 INFO: $/ will be set to 2
Bad file descriptor at readline_test.pl line 30, <F> chunk 3.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=2,PERLIO=stdio...
 INFO: $/ will be set to 2
 INFO: File /dev/stdin has been read, nbytes = 5
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=1k,PERLIO=perlio...
 INFO: $/ will be set to 1024
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=1k,PERLIO=stdio...
 INFO: $/ will be set to 1024
 INFO: File /dev/stdin has been read, nbytes = 5



Expected results:
each run of perl should complete without die and show number of bytes on input
(4 for first 8 tests, 5 for remaining tests) 

Additional info:
if PERLIO=perlio is used and there is actual I/O error in data file, the
readline_test.pl dies with inappropriate error message 
'Bad file descriptor' rather than 'Input/output error'
im most cases.

This can be easily shown with truncated ISO-9660 image file, loop mounted.
Should I also include test cases for this?

Comment 1 Wojciech Pilorz 2007-01-01 23:46:05 UTC
Created attachment 144615 [details]
readline_test.pl test script

Comment 2 Wojciech Pilorz 2007-01-01 23:48:51 UTC
Created attachment 144616 [details]
readline_test.bash run readline_test.pl 16 times with different settings and data

Comment 3 Wojciech Pilorz 2007-01-02 00:32:53 UTC
Created attachment 144617 [details]
how to test I/O errors and readline behaviour

I am showing a transcript of another test;
Run this from directory where readline_test.pl is  saved;

1. create a subdir and one test file with 400000 lines in that subdir; the file
size is about 6.76 MiB
2. create ISO9660 + rockridge image from that directory with mkisofs
3. create truncated image 5 MiB long
4. mount that truncated image through loop
5. run readline_test.pl for file in that mounted truncated image
  tests show that with PERLIO=stdio correct error message is displayed, while
  with PERLIO=perlio the error message is in most cases inappropriate.
  The error message (from die $!) is correct (Input/output error) if $/ is set
to a reference to a number X such that the size of part of file ftest01 stored
in truncated image file is a whole multiple of X

Comment 4 Wojciech Pilorz 2007-01-02 11:49:31 UTC
I have tried with ActiveState Perl on Centos 4.4, version v5.8.8 build 819;
it does not show the bugs with PERLIO=stdio

Comment 5 Wojciech Pilorz 2007-04-11 23:07:53 UTC
Is there some hope for this bug to be corrected?

Wojtek

Comment 6 Marcela Mašláňová 2008-03-17 13:29:53 UTC
The testing with perl-5.10.0 also show reported problems. Similar bugs were
reported on perl upstream bugzilla. 

The first problem is wrong error message 'Bad file descriptor':
http://rt.perl.org/rt3/Public/Bug/Display.html?id=38285
They decided that isn't bug, but open the new one, which includes problem with
wrong end of line:
http://rt.perl.org/rt3/Public/Bug/Display.html?id=39060

The problem is possibly somewhere in perl::IO module.

Comment 7 Bug Zapper 2008-05-14 02:31:55 UTC
Changing version to '9' as part of upcoming Fedora 9 GA.
More information and reason for this action is here:
http://fedoraproject.org/wiki/BugZappers/HouseKeeping

Comment 8 Wojciech Pilorz 2009-05-25 08:22:13 UTC
Running tests again on Fedora 10, perl-5.10.0-68.fc10.i386,

gives the following:

$ env LANG=C bash readline_test.bash                                                    
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=-1,PERLIO=perlio...                                    
 INFO: $/ will be set to undef                                                                               
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.                                                
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=-1,PERLIO=stdio...                                     
 INFO: $/ will be set to undef                                                                               
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.                                                
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=0,PERLIO=perlio...                                     
 INFO: $/ will not be set                                                                                    
Bad file descriptor at readline_test.pl line 30, <F> line 1.                                                 
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=0,PERLIO=stdio...                                      
 INFO: $/ will not be set                                                                                    
Bad file descriptor at readline_test.pl line 30, <F> line 1.
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=2,PERLIO=perlio...
 INFO: $/ will be set to 2
 INFO: File /dev/stdin has been read, nbytes = 4
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=2,PERLIO=stdio...
 INFO: $/ will be set to 2
 INFO: File /dev/stdin has been read, nbytes = 4
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=1k,PERLIO=perlio...
 INFO: $/ will be set to 1024
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234,CHUNKSIZE=1k,PERLIO=stdio...
 INFO: $/ will be set to 1024
 INFO: File /dev/stdin has been read, nbytes = 4
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=-1,PERLIO=perlio...
 INFO: $/ will be set to undef
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=-1,PERLIO=stdio...
 INFO: $/ will be set to undef
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=0,PERLIO=perlio...
 INFO: $/ will not be set
 INFO: File /dev/stdin has been read, nbytes = 5
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=0,PERLIO=stdio...
 INFO: $/ will not be set
Bad file descriptor at readline_test.pl line 30, <F> line 1.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=2,PERLIO=perlio...
 INFO: $/ will be set to 2
Bad file descriptor at readline_test.pl line 30, <F> chunk 3.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=2,PERLIO=stdio...
 INFO: $/ will be set to 2
 INFO: File /dev/stdin has been read, nbytes = 5
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=1k,PERLIO=perlio...
 INFO: $/ will be set to 1024
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.
 __ running readline_test.pl for stdin=1234\n,CHUNKSIZE=1k,PERLIO=stdio...
 INFO: $/ will be set to 1024
 INFO: File /dev/stdin has been read, nbytes = 5


and then testing broken data (truncated ISO filesystem):

$env CHUNKSIZE=-1 PERLIO=perlio perl -w readline_test.pl /mnt/looptest/ftest01                     
 INFO: $/ will be set to undef                                                                    
Bad file descriptor at readline_test.pl line 30, <F> chunk 1.                                     
$env CHUNKSIZE=-1 PERLIO=stdio perl -w readline_test.pl /mnt/looptest/ftest01                      
 INFO: $/ will be set to undef                                                                    
Input/output error at readline_test.pl line 30, <F> chunk 1.                                      
$env CHUNKSIZE=0 PERLIO=perlio perl -w readline_test.pl /mnt/looptest/ftest01                      
 INFO: $/ will not be set                                                                         
Bad file descriptor at readline_test.pl line 30, <F> line 294486.                                 
$env CHUNKSIZE=0 PERLIO=stdio perl -w readline_test.pl /mnt/looptest/ftest01                       
 INFO: $/ will not be set                                                                         
Input/output error at readline_test.pl line 30, <F> line 294486.                                  
$env CHUNKSIZE=2k PERLIO=perlio perl -w readline_test.pl /mnt/looptest/ftest01                     
 INFO: $/ will be set to 2048                                                                     
Input/output error at readline_test.pl line 30, <F> chunk 2534.                                   
$env CHUNKSIZE=4k PERLIO=perlio perl -w readline_test.pl /mnt/looptest/ftest01                     
 INFO: $/ will be set to 4096                                                                     
Input/output error at readline_test.pl line 30, <F> chunk 1267.                                   
$env CHUNKSIZE=8k PERLIO=perlio perl -w readline_test.pl /mnt/looptest/ftest01                     
 INFO: $/ will be set to 8192                                                                     
Bad file descriptor at readline_test.pl line 30, <F> chunk 634.                                   
$env CHUNKSIZE=32k PERLIO=perlio perl -w readline_test.pl /mnt/looptest/ftest01                    
 INFO: $/ will be set to 32768                                                                    
Bad file descriptor at readline_test.pl line 30, <F> chunk 159.

Comment 9 Stepan Kasal 2009-06-03 18:50:49 UTC
Thank you very much, Wojciech, for your patience.
I created a patch and submitted it upstream, see
http://rt.perl.org/rt3/Public/Bug/Display.html?id=39060

The patch also adds a new test, inspired by your test script.

Fixed in perl-5.10.0-69.fc12


Note You need to log in before you can comment on or make changes to this bug.