develooper Front page | perl.perl5.porters | Postings from May 2013

[perl #54926] IO on active pipes fails after ithread fork in 5.8.8

Thread Next
From:
James E Keenan via RT
Date:
May 26, 2013 16:51
Subject:
[perl #54926] IO on active pipes fails after ithread fork in 5.8.8
Message ID:
rt-3.6.HEAD-2650-1369587091-988.54926-15-0@perl.org
On Tue May 27 10:52:24 2008, johnh@isi.edu wrote:
> 
> This is a bug report for perl from johnh@isi.edu,
> generated with the help of perlbug 1.35 running under perl v5.8.8.
> 
> 
> -----------------------------------------------------------------
> [Please enter your report here]
> 
> IO on an active pipe fails after a thread fork,
> making
> 
> cat pipe_input.in | ./pipe_test.pl
> 
> behave DIFFERENTLY than
> 
> ./pipe_test.pl < cat_input.in
> 
> 
> This result appears to be because perl tries to lseek to the current
> position of the stream after fork and lseek fails with EISPIPE in the
> first (cat) case.  I'm guessing it considers the failed lseek to make
> the filehandle bad.  (This speculation is from strace.)
> 
> It seems to me (not having looked at perl's guts) that there is no
> need to lseek, at least for pipes, so perl should produce identical
> output in this case.  I.e., this difference is a bug.
> 
> This behavior is reproducable with the test case below.
> 
> The problem only happens when the file is active (i.e., one line of
>    input
> has been read before the thread fork).
> 
> ----------------------------------------
> #!/usr/bin/perl -w
> 
> # save as pipe_test.pl
> 
> use IO::Handle;
> use threads;
> 
> my $in = new IO::Handle;
> $in->fdopen(fileno(STDIN), "r");
> 
> # comment out the next line and it works
> my($header) = $in->getline;
> print "Header, always correct: $header";
> 
> my $worker_thread = threads->new( sub {
>    my $count = 0;
>    my $line;
>    while ($line = $in->getline) {
>        print "$count: $line";
>            $count++;
> 	   };
> 	   return $count;
>     } );
> 
> my $result = $worker_thread->join;
> 
> print "\nline count: $result\n\n";
> print "Count will incorrectly be 0 if run with cat pipe_input.in |
>    perl pipe_test.pl,\n" .
>     "or 2 if run with perl pipe_test.pl <pipe_input.in.\n" .
>     "It should be the same in both cases.\n" .
>     "Suspected bug: after fork, perl lseeks on \$in, which files if\n"
>    .
>     "it is a pipe (OS: linux 2.6.24 on Fedora 8, perl-5.8.8).\n" .
>     "(Note: it works if there is no pre-existing IO on the file,\n" .
>     "i.e., if first getline is commented out.)\n";
> 
> 
> exit 0;
> ----------------------------------------
> 
> sample input file (pipe_input.in):
> 
> #h header
> line one
> line two
> 
> ----------------------------------------
> 
> sample tail of the strace -f output:
> 
> ...
> read(3, "", 4096)                       = 0
> close(3)                                = 0
> ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbfb7b9e8) = -1 EINVAL
>    (Invalid argument)
> _llseek(0, 0, 0xbfb7ba10, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
> fstat64(0, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
> fcntl64(0, F_SETFD, 0)                  = 0
> read(0, "#h header\nline one\nline two\n", 4096) = 28
> write(1, "Header, always correct: #h heade"..., 34) = 34
> _llseek(0, 10, 0xbfb7bb60, SEEK_SET)    = -1 ESPIPE (Illegal seek)
> mmap2(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
>    -1, 0) = 0xb7cfa000
> brk(0x9ada000)                          = 0x9ada000
> ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbfb7ba48) = -1 EINVAL
>    (Invalid argument)
> _llseek(0, 0, 0xbfb7ba70, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
> ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo
>    ...}) = 0
> _llseek(1, 0, 0xbfb7ba70, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
> ioctl(2, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbfb7ba48) = -1 ENOTTY
>    (Inappropriate ioctl for device)
> _llseek(2, 0, [98043], SEEK_CUR)        = 0
> ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0xbfb7ba48) = -1 EINVAL
>    (Invalid argument)
> _llseek(0, 0, 0xbfb7ba70, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
> brk(0x9afb000)                          = 0x9afb000
> brk(0x9b1c000)                          = 0x9b1c000
> brk(0x9b3d000)                          = 0x9b3d000
> mmap2(NULL, 10489856, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
>    -1, 0) = 0xb72f9000
> mprotect(0xb72f9000, 4096, PROT_NONE)   = 0
> clone(Process 29195 attached (waiting for parent)
> Process 29195 resumed (parent 29194 ready)
> child_stack=0xb7cf94b4,
>   
flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID,
>    parent_tidptr=0xb7cf9bd8, {entry_number:6, base_addr:0xb7cf9b90,
>    limit:1048575, seg_32bit:1, contents:0, read_exec_only:0,
>    limit_in_pages:1, seg_not_present:0, useable:1},
>    child_tidptr=0xb7cf9bd8) = 29195
> [pid 29195] set_robust_list(0xb7cf9be0, 0xc) = 0
> [pid 29195] read(0, "", 4096)           = 0
> [pid 29195] _exit(0)                    = ?
> Process 29195 detached
> munmap(0xb7cfa000, 135168)              = 0
> write(1, "\nline count: 0\n\n", 16)     = 16
> write(1, "Count will be 0 if run with cat "..., 231) = 231
> _llseek(0, 10, 0xbfb7b9e0, SEEK_SET)    = -1 ESPIPE (Illegal seek)
> munmap(0xb7d1b000, 135168)              = 0
> exit_group(0)                           = ?
> 
> 
> [Please do not change anything below this line]
> -----------------------------------------------------------------
> ---
> Flags:
>     category=core
>     severity=medium
> ---
> This perlbug was built using Perl v5.8.8 in the Red Hat build system.
> It is being executed now by Perl v5.8.8 - Tue Apr 29 02:54:41 EDT
>    2008.
> 

Could someone familiar with threads try this out on Perl 5.18 and make
some suggestions?

Thank you very much.
Jim Keenan

---
via perlbug:  queue: perl5 status: new
https://rt.perl.org:443/rt3/Ticket/Display.html?id=54926

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About