sysread(socket..) problem on perl 5.8.0 linux

B

Bean

Hi,

I've been debugging a socket read problem using perl 5.8.0 on RH8.0. The
following script fails consistantly on perl 5.8.0 but works fine on 5.8.3
and 5.8.5. It also works if either side (client or server) is _not_ running
on 5.8.0.

The problem is that the client sysread returns 0 (eof) when the server has
sent data. I've strace'd both sides and the server thinks it has sent 1024
bytes but the client receives nothing and sysread returns 0, strace reports
ESPIPE on the socket fd.

Am I doing something wrong in the code? Could it be a perl bug or maybe a
hardware problem? My different versions of perl are all on different
machines.

Can any one help?

Regards, Ben.

Output:

$ ./sfile.pl server
sent header FILE:2082:1024
server wrote a block 1024 in size
server wrote a block 1024 in size
server wrote a block 34 in size
write total size = 2082

$ ./sfile.pl client
read header FILE:2082:1024
trying to reading 1024
sysread returned 0
read total size = 0

Script:

#!/usr/bin/perl
# -*- perl -*-
use strict;
use warnings;
use IO::Socket::INET;
use IO::File;

$|=1;

server() if $ARGV[0] eq 'server';
client() if $ARGV[0] eq 'client';

sub server
{
my $s = IO::Socket::INET->new
(
LocalPort => 9999,
Listen => 1,
Proto => 'tcp',
Type => SOCK_STREAM,
ReuseAddr => 1,
) || die $!;

$s->autoflush(1);
$s->blocking(1);

while (1)
{
my $n = $s->accept;
write_file($n,$0);
$n->close;
}
}


sub client
{
my $s = IO::Socket::INET->new
(
PeerAddr => 'localhost',
PeerPort => 9999,
Proto => 'tcp',
Type => SOCK_STREAM,
) || die $!;

$s->autoflush(1);
$s->blocking(1);

read_file($s);

$s->close;
}

sub write_file
{
my $s = shift;
my $f = shift;

die unless -f $f;
my $fh = IO::File->new("<$f") || die $!;

my $bs = 1024;
my $sz = (stat($f))[7];
my $ts = 0; # total size written

if ( $sz < $bs )
{
$bs = $sz;
}

my $head = "FILE:$sz:$bs\n";
die "header write failed" if syswrite($s,$head,length($head)) !=
length($head);
print "sent header $head";


while ( $bs )
{
my $buf = '';
my $wr = sysread($fh,$buf,$bs) || die "reading $bs from file: $!";
$ts += $wr;

my $sw = syswrite($s,$buf,$wr);
print "short write!" if ( $sw != $wr );

print "server wrote a block $sw in size\n";

if ( ( $sz - $ts ) < $bs )
{
$bs = $sz - $ts;
}
}
print "write total size = $ts\n";
}

sub read_file
{
my $s = shift;
my $head = $s->getline || die "header read failed";
print "read header $head";

my ($ts, $bs);
if ( $head =~ /FILE\:(\d+)\:(\d+)\n/ )
{
($ts, $bs) = ($1,$2);
}
else
{
die "incorrect header format";
}

my $tr = 0; # total size read
while ($bs)
{
if ( ( $ts - $tr ) < $bs )
{
$bs = $ts - $tr;
}

print "trying to reading $bs\n";
my $buf = '';
my $rd = sysread($s,$buf,$bs);
if ( $rd > 0 )
{
$tr += $rd;
}
else
{
print "sysread returned $rd\n";
last;
}

}
print "read total size = $tr\n";


}

My perl is:

Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration:
Platform:
osname=linux, osvers=2.4.18-11smp, archname=i386-linux-thread-multi
uname='linux daffy.perf.redhat.com 2.4.18-11smp #1 smp thu aug 15
06:41:59 edt 2002 i686 i686 i386 gnulinux '
config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -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 -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less
-isr'
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='gcc', ccflags
='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-I/usr/include/gdbm',
optimize='-O2 -march=i386 -mcpu=i686',
cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -I/usr/include/gdbm'
ccversion='', gccversion='3.2 20020822 (Red Hat Linux Rawhide 3.2-5)',
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=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil
perllibs=-lnsl -ldl -lm -lpthread -lc -lcrypt -lutil
libc=/lib/libc-2.2.92.so, so=so, useshrplib=true, libperl=libperl.so
gnulibc_version='2.2.92'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef,
ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE'
cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'


Characteristics of this binary (from libperl):
Compile-time options: MULTIPLICITY USE_ITHREADS USE_LARGE_FILES
PERL_IMPLICIT_CONTEXT
Built under linux
Compiled at Sep 1 2002 23:56:49
@INC:
/usr/lib/perl5/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/5.8.0
/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.0
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.0
/usr/lib/perl5/vendor_perl
 
B

Bean

After more coffee I realized i've mixed buffered/non-buffered IO :/

Ben.


Bean said:
Hi,

I've been debugging a socket read problem using perl 5.8.0 on RH8.0. The
following script fails consistantly on perl 5.8.0 but works fine on 5.8.3
and 5.8.5. It also works if either side (client or server) is _not_
running on 5.8.0.

The problem is that the client sysread returns 0 (eof) when the server has
sent data. I've strace'd both sides and the server thinks it has sent 1024
bytes but the client receives nothing and sysread returns 0, strace
reports ESPIPE on the socket fd.

Am I doing something wrong in the code? Could it be a perl bug or maybe a
hardware problem? My different versions of perl are all on different
machines.

Can any one help?

Regards, Ben.

Output:

$ ./sfile.pl server
sent header FILE:2082:1024
server wrote a block 1024 in size
server wrote a block 1024 in size
server wrote a block 34 in size
write total size = 2082

$ ./sfile.pl client
read header FILE:2082:1024
trying to reading 1024
sysread returned 0
read total size = 0

Script:

#!/usr/bin/perl
# -*- perl -*-
use strict;
use warnings;
use IO::Socket::INET;
use IO::File;

$|=1;

server() if $ARGV[0] eq 'server';
client() if $ARGV[0] eq 'client';

sub server
{
my $s = IO::Socket::INET->new
(
LocalPort => 9999,
Listen => 1,
Proto => 'tcp',
Type => SOCK_STREAM,
ReuseAddr => 1,
) || die $!;

$s->autoflush(1);
$s->blocking(1);

while (1)
{
my $n = $s->accept;
write_file($n,$0);
$n->close;
}
}


sub client
{
my $s = IO::Socket::INET->new
(
PeerAddr => 'localhost',
PeerPort => 9999,
Proto => 'tcp',
Type => SOCK_STREAM,
) || die $!;

$s->autoflush(1);
$s->blocking(1);

read_file($s);

$s->close;
}

sub write_file
{
my $s = shift;
my $f = shift;

die unless -f $f;
my $fh = IO::File->new("<$f") || die $!;

my $bs = 1024;
my $sz = (stat($f))[7];
my $ts = 0; # total size written

if ( $sz < $bs )
{
$bs = $sz;
}

my $head = "FILE:$sz:$bs\n";
die "header write failed" if syswrite($s,$head,length($head)) !=
length($head);
print "sent header $head";


while ( $bs )
{
my $buf = '';
my $wr = sysread($fh,$buf,$bs) || die "reading $bs from file: $!";
$ts += $wr;

my $sw = syswrite($s,$buf,$wr);
print "short write!" if ( $sw != $wr );

print "server wrote a block $sw in size\n";

if ( ( $sz - $ts ) < $bs )
{
$bs = $sz - $ts;
}
}
print "write total size = $ts\n";
}

sub read_file
{
my $s = shift;
my $head = $s->getline || die "header read failed";
print "read header $head";

my ($ts, $bs);
if ( $head =~ /FILE\:(\d+)\:(\d+)\n/ )
{
($ts, $bs) = ($1,$2);
}
else
{
die "incorrect header format";
}

my $tr = 0; # total size read
while ($bs)
{
if ( ( $ts - $tr ) < $bs )
{
$bs = $ts - $tr;
}

print "trying to reading $bs\n";
my $buf = '';
my $rd = sysread($s,$buf,$bs);
if ( $rd > 0 )
{
$tr += $rd;
}
else
{
print "sysread returned $rd\n";
last;
}

}
print "read total size = $tr\n";


}

My perl is:

Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration:
Platform:
osname=linux, osvers=2.4.18-11smp, archname=i386-linux-thread-multi
uname='linux daffy.perf.redhat.com 2.4.18-11smp #1 smp thu aug 15
06:41:59 edt 2002 i686 i686 i386 gnulinux '
config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -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 -Ubincompat5005 -Uversiononly
-Dpager=/usr/bin/less -isr'
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='gcc', ccflags
='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-I/usr/include/gdbm',
optimize='-O2 -march=i386 -mcpu=i686',
cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -I/usr/include/gdbm'
ccversion='', gccversion='3.2 20020822 (Red Hat Linux Rawhide 3.2-5)',
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=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil
perllibs=-lnsl -ldl -lm -lpthread -lc -lcrypt -lutil
libc=/lib/libc-2.2.92.so, so=so, useshrplib=true, libperl=libperl.so
gnulibc_version='2.2.92'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef,
ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE'
cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'


Characteristics of this binary (from libperl):
Compile-time options: MULTIPLICITY USE_ITHREADS USE_LARGE_FILES
PERL_IMPLICIT_CONTEXT
Built under linux
Compiled at Sep 1 2002 23:56:49
@INC:
/usr/lib/perl5/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/5.8.0
/usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/site_perl/5.8.0
/usr/lib/perl5/site_perl
/usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
/usr/lib/perl5/vendor_perl/5.8.0
/usr/lib/perl5/vendor_perl
.
 
A

Anno Siegel

Bean said:
After more coffee I realized i've mixed buffered/non-buffered IO :/

....and to tell us that you had to quote 250 lines of your own posting?

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top