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

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

johnh @ isi . edu
May 28, 2008 02:51
[perl #54926] IO on active pipes fails after ithread fork in 5.8.8
Message ID:
# New Ticket Created by 
# Please include the string:  [perl #54926]
# in the subject line of all future correspondence about this issue. 
# <URL: >

This is a bug report for perl from,
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,

cat | ./

behave DIFFERENTLY than

./ < 

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

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";
	   return $count;
    } );

my $result = $worker_thread->join;

print "\nline count: $result\n\n";
print "Count will incorrectly be 0 if run with cat | perl,\n" .
    "or 2 if run with perl <\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 (

#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]
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.

Site configuration information for perl v5.8.8:

Configured by Red Hat, Inc. at Tue Apr 29 02:54:41 EDT 2008.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration:
    osname=linux, osvers=2.6.18-53.1.14.el5xen, archname=i386-linux-thread-multi
    uname='linux 2.6.18-53.1.14.el5xen #1 smp tue feb 19 07:33:17 est 2008 i686 i686 i386 gnulinux '
    config_args='-des -Doptimize=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -Dversion=5.8.8 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl=n -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr -Dd_gethostent_r_proto -Ud_endhostent_r_proto -Ud_sethostent_r_proto -Ud_endprotoent_r_proto -Ud_setprotoent_r_proto -Ud_endservent_r_proto -Ud_setservent_r_proto -Dinc_version_list=5.8.7 5.8.6 5.8.5 -Dscriptdir=/usr/bin'
    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
    cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
    optimize='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -Wdeclaration-after-statement -I/usr/local/include -I/usr/include/gdbm'
    ccversion='', gccversion='4.1.2 20070925 (Red Hat 4.1.2-33)', 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='gcc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lresolv -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/, so=so, useshrplib=true,
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE'
    cccdlflags='-fPIC', lddlflags='-shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -L/usr/local/lib'

Locally applied patches:

@INC for perl v5.8.8:

Environment for perl v5.8.8:
    LANGUAGE (unset)
    LOGDIR (unset)
    PERL_BADLANG (unset)
    SHELL=/bin/bash Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About