Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.94k stars 553 forks source link

5.7.0-7483: Strange socket behaviour #2781

Closed p5pRT closed 20 years ago

p5pRT commented 23 years ago

Migrated from rt.perl.org#4549 (status was 'resolved')

Searchable as RT4549$

p5pRT commented 23 years ago

From @jhamisch

Hi\,

I've figured out a very strange behaviour perl 5.7.0 (APC 7483 installed) shows on socket read operations. I first found that\, when I tried to run mirror 2.9 using perl 5.7.0 and did some investigation in the problem. I've isolated the thing in a small client/server application\, with a server which just displays a small text upon being connected and a variety of client procedures connecting the server.

The server establishes its service on port 4242. You'll receive the correct text file if you're doing a 'telnet localhost 4242'. The following small perl program also results in a correct output​:

  #!/usr/local/bin/perl -w

  use FileHandle;   use Client;

  my $sh = new FileHandle;   $sh = Client​::tcp_connect( 'localhost'\, 4242);

  while( \<$sh>) {   print;   }

The module Client.pm provides the appropriate socket and connect system call.

The next small perl program results in a corrupted output​:

  #!/usr/local/bin/perl -w

  use FileHandle;   use Client;

  my $sh = new FileHandle;   $sh = Client​::tcp_connect( 'localhost'\, 4242);

  while( !eof( $sh ) ){   my( $res) = &line( $sh );   last if $res eq 'eof';   }

  sub line {   my( $fh ) = @​_;

  while( \<$fh> ){   print "$_";   return( "ok" );   }   return( "eof" );   }

Instead of the orginal lines of text a - at a first glance - random character is displayed at the beginning of each line. Having a closer look at the things displayed\, it turns out\, that each of these 'random' characters form some content of the orginal text file in my case beginning at character 7317 ... for my point of view this is very\, very mysterious!

Furthermore it turns out\, that the first client example does a connect system call followed by a few read calls as the following truss output shows​:

.... close(4) = 0 connect(3\, 0x10022D8E0\, 16\, 1) = 0 fstat(3\, 0xFFFFFFFF7FFFCDA0) = 0 ioctl(3\, TCGETA\, 0xFFFFFFFF7FFFCCDC) Err#22 EINVAL read(3\, " / * L I N T L I B R A"..\, 8192) = 8192 ioctl(1\, TCGETA\, 0xFFFFFFFF7FFFEEAC) Err#25 ENOTTY fstat(1\, 0xFFFFFFFF7FFFEF70) = 0 read(3\, " n \, i n t y \, i n"..\, 8192) = 8192 read(3\, " t ( * i n i t ) ( W I"..\, 8192) = 8192 read(3\, " n t v i d p u t s ( c"..\, 8192) = 235 write(1\, " t ( * i n i t ) ( W I"..\, 8192) = 8192 read(3\, 0x100086C64\, 8192) = 0 ....

In opposite to this correct behaviour\, the second example does lots of recv calls in addition to the 3 read calls.

.... close(4) = 0 connect(3\, 0x10022D8E0\, 16\, 1) = 0 getsockopt(3\, 65535\, 4104\, 0xFFFFFFFF7FFFF24C\, 0xFFFFFFFF7FFFF248\, 1) = 0 getsockname(3\, 0xFFFFFFFF7FFFEF88\, 0xFFFFFFFF7FFFF090\, 1) = 0 getsockopt(3\, 65535\, 4104\, 0xFFFFFFFF7FFFF098\, 0xFFFFFFFF7FFFF094\, 1) = 0 recv(3\, " /"\, 1\, 0) = 1 fstat(3\, 0xFFFFFFFF7FFFF080) = 0 ioctl(3\, TCGETA\, 0xFFFFFFFF7FFFEFBC) Err#22 EINVAL read(3\, " * L I N T L I B R A R"..\, 8192) = 8192 ioctl(1\, TCGETA\, 0xFFFFFFFF7FFFEE9C) Err#25 ENOTTY fstat(1\, 0xFFFFFFFF7FFFEF60) = 0 getsockopt(3\, 65535\, 4104\, 0xFFFFFFFF7FFFF24C\, 0xFFFFFFFF7FFFF248\, 1) = 0 getsockname(3\, 0xFFFFFFFF7FFFEF88\, 0xFFFFFFFF7FFFF090\, 1) = 0 getsockopt(3\, 65535\, 4104\, 0xFFFFFFFF7FFFF098\, 0xFFFFFFFF7FFFF094\, 1) = 0 recv(3\, " \,"\, 1\, 0) = 1 getsockopt(3\, 65535\, 4104\, 0xFFFFFFFF7FFFF24C\, 0xFFFFFFFF7FFFF248\, 1) = 0 getsockname(3\, 0xFFFFFFFF7FFFEF88\, 0xFFFFFFFF7FFFF090\, 1) = 0 getsockopt(3\, 65535\, 4104\, 0xFFFFFFFF7FFFF098\, 0xFFFFFFFF7FFFF094\, 1) = 0 recv(3\, " "\, 1\, 0) = 1 getsockopt(3\, 65535\, 4104\, 0xFFFFFFFF7FFFF24C\, 0xFFFFFFFF7FFFF248\, 1) = 0 getsockname(3\, 0xFFFFFFFF7FFFEF88\, 0xFFFFFFFF7FFFF090\, 1) = 0 getsockopt(3\, 65535\, 4104\, 0xFFFFFFFF7FFFF098\, 0xFFFFFFFF7FFFF094\, 1) = 0 recv(3\, " i"\, 1\, 0) = 1 getsockopt(3\, 65535\, 4104\, 0xFFFFFFFF7FFFF24C\, 0xFFFFFFFF7FFFF248\, 1) = 0 ....

Assuming\, that the additional eof() call in the second example causes this behaviour\, I did another two tests​:

  #!/usr/local/bin/perl -w

  use FileHandle;   use Client;

  my $sh = new FileHandle;   $sh = Client​::tcp_connect( 'localhost'\, 4242);

  while( !eof( $sh ) ){   print \<$sh>;   }

and

  #!/usr/local/bin/perl -w

  use FileHandle;   use Client;

  my $sh = new FileHandle;   $sh = Client​::tcp_connect( 'localhost'\, 4242);

  while( !eof( $sh ) ){   while( \<$sh>) {   print;   break;   }   }

The first one worked out fine\, while the second one showed the buggy behaviour! Nevertheless the last test doens't show the problem\, if the 'last' statement is removed!

So my conclusion (without analyzing the underlaying perl code) is\, that caused by the second block of code the 'recv' system calls are forced and that these 'recv' cause side effects with the 'read' calls.

My perl 5.7.0 environment is​:

Summary of my perl5 (revision 5.0 version 7 subversion 0) configuration​:   Platform​:   osname=solaris\, osvers=2.8\, archname=sun4-solaris-thread-multi-ld   uname='sunos voi 5.8 generic sun4u sparc sunw\,ultra-5_10 '   config_args='-d'   hint=previous\, useposix=true\, d_sigaction=define   usethreads=define use5005threads=undef useithreads=define usemultiplicity=define   useperlio=undef d_sfio=undef uselargefiles=define usesocks=define   use64bitint=define use64bitall=define uselongdouble=define   Compiler​:   cc='cc'\, ccflags ='-D_REENTRANT -DSOCKS -I/usr/local/include -I/opt/socks5/include -I/usr/local/BerkeleyDB.3.1/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -xarch=v9'\,   optimize='-g -xarch=v9'\,   cppflags='-D_REENTRANT -DSOCKS -I/usr/local/include -I/opt/socks5/include -I/usr/local/BerkeleyDB.3.1/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -xarch=v9'   ccversion='Sun WorkShop 6 2000/04/07 C 5.1'\, gccversion=''\, gccosandvers=''   intsize=4\, longsize=8\, ptrsize=8\, doublesize=8\, byteorder=87654321   d_longlong=define\, longlongsize=8\, d_longdbl=define\, longdblsize=16   ivtype='long'\, ivsize=8\, nvtype='long double'\, nvsize=16\, Off_t='off_t'\, lseeksize=8   alignbytes=16\, usemymalloc=y\, prototype=define   Linker and Libraries​:   ld='cc'\, ldflags ='-g -xarch=v9 -L/usr/local/lib -R/usr/local/lib -L/opt/SUNWspro/WS6/lib/v9 -L/opt/socks5/lib -L/usr/local/BerkeleyDB.3.1/lib -R/usr/local/BerkeleyDB.3.1/lib -L/usr/krb5/lib -R/usr/krb5/lib'   libpth=/usr/local/lib /opt/SUNWspro/WS6/lib/v9 /lib /usr/lib /usr/ccs/lib /opt/socks5/lib /usr/local/BerkeleyDB.3.1/lib /usr/krb5/lib   libs=-lsocket -lnsl -ldb -ldl -lm -lsunmath -lposix4 -lpthread -lc -lsec -lsocks5 -lgssapi_krb5   perllibs=-lsocket -lnsl -ldl -lm -lsunmath -lposix4 -lpthread -lc -lsec -lsocks5 -lgssapi_krb5   libc=/usr/lib/sparcv9/libc.so\, so=so\, useshrplib=true\, libperl=libperl.so.7.0   Dynamic Linking​:   dlsrc=dl_dlopen.xs\, dlext=so\, d_dlsymun=undef\, ccdlflags=' -R /opt/perl_5.7.0/lib/5.7.0/sun4-solaris-thread-multi-ld/CORE'   cccdlflags='-KPIC'\, lddlflags=' -G -xarch=v9 -L/usr/local/lib -R/usr/local/lib -L/opt/SUNWspro/WS6/lib/v9 -L/opt/socks5/lib -L/usr/local/BerkeleyDB.3.1/lib -R/usr/local/BerkeleyDB.3.1/lib -L/usr/krb5/lib -R/usr/krb5/lib'

Characteristics of this binary (from libperl)​:   Compile-time options​: MULTIPLICITY USE_ITHREADS USE_64_BIT_INT USE_64_BIT_ALL USE_LONG_DOUBLE USE_LARGE_FILES USE_SOCKS PERL_IMPLICIT_CONTEXT   Locally applied patches​:   DEVEL7481   Built under solaris   Compiled at Oct 30 2000 13​:06​:46   @​INC​:   /opt/perl_5.7.0/lib/5.7.0/sun4-solaris-thread-multi-ld   /opt/perl_5.7.0/lib/5.7.0   /opt/perl_5.7.0/lib/site_perl/5.7.0/sun4-solaris-thread-multi-ld   /opt/perl_5.7.0/lib/site_perl/5.7.0   /opt/perl_5.7.0/lib/site_perl   /opt/perl_5.7.0/lib/vendor_perl/5.7.0/sun4-solaris-thread-multi-ld   /opt/perl_5.7.0/lib/vendor_perl/5.7.0   /opt/perl_5.7.0/lib/vendor_perl   .

I've attached my little 'test-suite' as gzipped tar file to this mail.

Any help of hints would be welcome ...

Regards -- Jens


  / +##+|##+ STRAWBERRY Jens Hamisch +v#+v v##+ EDV-Systeme GmbH Managing director / v v\v | . . . | Brauneckweg 2 Car (Voice)​: (+49 172) 81 04 162 | . | D-82549 Koenigsdorf Voice​: (+49 8179) 9305-50 | . | Fax​: (+49 8179) 9305-38 \ . / Tel./Fax​: (+49 8179) 9305-50 Email​: jens@​Strawberry.COM   \____/ Strawberry@​Strawberry.COM

p5pRT commented 23 years ago

From @jhamisch

cs.tar.gz

p5pRT commented 23 years ago

From @jhamisch

Hi\,

as suggested by Nick\, I've checked if the SOCKS- and close-patch is required even if PerlIO is used. It turns out\, that​:

  perl@​7847 as is with SOCKS enabled   Compiles on   * Solaris 8 v9   * Solaris 8 i86pc   * Solaris 2.6 sparc has not been tested

  but t/lib/io_sock.t (close-bug) fails on   * Solaris 8 v9   * Solaris 8 i86pc   * Solaris 2.6 sparc has not been tested

  perl@​7847 with SOCKS and PerlIO enabled with the following small   modification​:   perl.h​:   * Don't define SOCKS_64BIT_BUG if USE_PERLIO is set  
  Compiles on   * none   * Solaris 2.6 sparc has not been tested  
  Fails to compile on   * Solaris 8 v9   * Solaris 8 i86pc

  because the function PerlIO_fdupopen is not defined

  perl@​7847 with SOCKS and PerlIO enabled with the following small   modification​:   perl.h​:   * Don't define SOCKS_64BIT_BUG if USE_PERLIO is set   perlio.h​:   * #define PerlIO_fdupopen(f) (f)   as perlsdio.h does

  Compiles on   * Solaris 8 v9   * Solaris 8 i86pc   * Solaris 2.6 sparc has not been tested

  and completes the testsuite on success on   * Solaris 8 v9

  but t/lib/io_sock.t (close-bug) fails on   * Solaris 8 i86pc   * Solaris 2.6 sparc has not been tested

  perl@​7847 with SOCKS and PerlIO enabled with the following big   modification​:   perlio.h​:   * #define PerlIO_fdupopen(f) (f)   as perlsdio.h does   doio.c pp_sys.c perl.h perlsdio.h​:   * remove all SOCKS_64BIT_BUG code   Configure​:   * force PerlIO if SOCKS is configured

  Compiles on   * Solaris 8 v9   * Solaris 8 i86pc   * Solaris 2.6 sparc has not been tested

  and completes the testsuite on success on   * Solaris 8 v9

  but t/lib/io_sock.t (close-bug) fails on   * Solaris 8 i86pc   * Solaris 2.6 sparc has not been tested

  perl@​7847 with SOCKS and PerlIO enabled with the following bigger   modification​:   perlio.h​:   * #define PerlIO_fdupopen(f) (f)   as perlsdio.h does   doio.c pp_sys.c perl.h perlsdio.h​:   * remove all SOCKS_64BIT_BUG code   Configure​:   * force PerlIO if SOCKS is configured   perlio.c​:   * Apply the close-patch to PerlIOStdio_close

  Compiles on   * Solaris 8 v9   * Solaris 8 i86pc   * Solaris 2.6 sparc is currently under test

  and completes the testsuite on success   * Solaris 8 v9   * Solaris 8 i86pc   * Solaris 2.6 sparc is currently under test

The attached patch​:   * adds a workaround to the PerlIO_fdupopen problem. This should   be doublechecked by Nick!   * removes all SOCKS_64BIT_BUG code   * forces PerlIO if SOCKS is configured   * applies the close-patch to PerlIOStdio_close   * adds the SOCKS c/s tests to t/lib/io_sock.t

and should be the final solution to the SOCKS problem. Removing all the Socks/64 bit workarounds requires\, that PerlIO is forced!

Hey\, it took me a couple of hours to figure all this out today ... ... maybe it's possible to add an acknowlegdement somewhere in the release notes for the DeTeSystem GmbH who paid me as consultant during this time\, and the weeks before! I couldn't have done all these tests and patches without them. That's my idea\, not theirs ...

I'm looking forward to your reactions to the attached patch.  
-- Jens


  / +##+|##+ STRAWBERRY Jens Hamisch +v#+v v##+ EDV-Systeme GmbH Managing director / v v\v | . . . | Brauneckweg 2 Car (Voice)​: (+49 172) 81 04 162 | . | D-82549 Koenigsdorf Voice​: (+49 8179) 9305-50 | . | Fax​: (+49 8179) 9305-38 \ . / Tel./Fax​: (+49 8179) 9305-50 Email​: jens@​Strawberry.COM   \____/ Strawberry@​Strawberry.COM

p5pRT commented 23 years ago

From @jhamisch

*** ./perl.h.FCS Fri Nov 24 16​:05​:41 2000 --- ./perl.h Fri Nov 24 16​:14​:21 2000 *************** *** 737\,745 ****   # undef INCLUDE_PROTOTYPES   # undef PERL_SOCKS_NEED_PROTOTYPES   # endif - # ifdef USE_64_BIT_ALL - # define SOCKS_64BIT_BUG /* until proven otherwise */ - # endif   # endif   # ifdef I_NETDB   # include \<netdb.h> --- 737\,742 ---- *************** *** 2819\,2834 ****   #define PERL_CKDEF(s) OP *s (pTHX_ OP *o);   #define PERL_PPDEF(s) OP *s (pTHX);  
- #ifdef SOCKS_64BIT_BUG - typedef struct __s64_iobuffer { - struct __s64_iobuffer *next\, *last; /* Queue pointer */ - PerlIO *fp; /* Assigned file pointer */ - int cnt; /* Buffer counter */ - int size; /* Buffer size */ - int *buffer; /* The buffer */ - } S64_IOB; - #endif -   #include "proto.h"  
  #ifdef PERL_OBJECT --- 2816\,2821 ---- *** ./perlio.h.FCS Fri Nov 24 15​:25​:04 2000 --- ./perlio.h Fri Nov 24 15​:25​:13 2000 *************** *** 303\,309 ****   extern int PerlIO_setpos (PerlIO *\,const Fpos_t *);   #endif   #ifndef PerlIO_fdupopen ! extern PerlIO * PerlIO_fdupopen (PerlIO *);   #endif   #ifndef PerlIO_isutf8   extern int PerlIO_isutf8 (PerlIO *); --- 303\,310 ----   extern int PerlIO_setpos (PerlIO *\,const Fpos_t *);   #endif   #ifndef PerlIO_fdupopen ! #define PerlIO_fdupopen(f) (f) ! /* extern PerlIO * PerlIO_fdupopen (PerlIO *); */   #endif   #ifndef PerlIO_isutf8   extern int PerlIO_isutf8 (PerlIO *); *** ./Configure.FCS Fri Nov 24 16​:04​:31 2000 --- ./Configure Fri Nov 24 16​:30​:48 2000 *************** *** 3673\,3679 ****   cat \<\<EOM  
  Perl can be built to use the SOCKS proxy protocol library. To do so\, ! Configure must be run with -Dusesocks.  
  If this doesn't make any sense to you\, just accept the default '$dflt'.   EOM --- 3673\,3680 ----   cat \<\<EOM  
  Perl can be built to use the SOCKS proxy protocol library. To do so\, ! Configure must be run with -Dusesocks. Configuring Perl for SOCKS ! will implicitely configure PerlIO.  
  If this doesn't make any sense to you\, just accept the default '$dflt'.   EOM *************** *** 3686\,3691 **** --- 3687\,3696 ----   set usesocks   eval $setvar  
+ case "$usesocks" in + $define|true|[yY]*) useperlio="$define" ;; + esac +   : Looking for optional libraries   echo " "   echo "Checking for optional libraries..." >&4 *************** *** 7436\,7456 ****   problems with some extension modules. Using PerlIO with stdio is safe\,   but it is slower than plain stdio and therefore is not the default.  
  If this doesn't make any sense to you\, just accept the default '$dflt'.   EOM ! rp='Use the experimental PerlIO abstraction layer?' ! . ./myread ! case "$ans" in ! y|Y)   val="$define"   ;;
! *)
  echo "Ok\, doing things the stdio way"   val="$undef"   ;;   esac - set useperlio - eval $setvar  
  case "$vendorprefix" in   '') d_vendorbin="$undef" --- 7441\,7476 ----   problems with some extension modules. Using PerlIO with stdio is safe\,   but it is slower than plain stdio and therefore is not the default.  
+ EOM + + case "$usesocks" in + $define|true|[yY]*) + cat \<\<EOM + The PerlIO abstraction layer is forced by the SOCKS configuration. + + EOM + useperlio="$define" + ;; + *) + cat \<\<EOM   If this doesn't make any sense to you\, just accept the default '$dflt'. +   EOM ! rp='Use the experimental PerlIO abstraction layer?' ! . ./myread ! case "$ans" in ! y|Y)   val="$define"   ;;
! *)
  echo "Ok\, doing things the stdio way"   val="$undef"   ;; + esac + set useperlio + eval $setvar + ;;   esac  
  case "$vendorprefix" in   '') d_vendorbin="$undef" *** ./embed.pl.FCS Fri Nov 24 16​:05​:41 2000 --- ./embed.pl Fri Nov 24 16​:15​:54 2000 *************** *** 1505\,1522 ****   p |UV |do_vecget |SV* sv|I32 offset|I32 size   p |void |do_vecset |SV* sv   p |void |do_vop |I32 optype|SV* sv|SV* left|SV* right - #if defined(SOCKS_64BIT_BUG) - p |Off_t |do_s64_tell |PerlIO* fp - p |SSize_t|do_s64_fread |void *buf|SSize_t count|PerlIO* fp - p |int |do_s64_getc |PerlIO* fp - p |int |do_s64_seek |PerlIO* fp|Off_t pos|int whence - p |int |do_s64_ungetc |int ch|PerlIO* fp - p |void |do_s64_delete_buffer|PerlIO* fp - Ajnop |void |do_s64_init_buffer - s |S64_IOB * |s64_get_buffer |PerlIO *f - s |S64_IOB * |s64_create_buffer |PerlIO *f - s |int |s64_malloc |S64_IOB *ptr - #endif   p |OP* |dofile |OP* term   Ap |I32 |dowantarray   Ap |void |dump_all --- 1505\,1510 ---- *** ./perlsdio.h.FCS Fri Nov 24 16​:05​:41 2000 --- ./perlsdio.h Fri Nov 24 16​:15​:26 2000 *************** *** 18\,28 ****   #define PerlIO_open fopen   #define PerlIO_fdopen fdopen   #define PerlIO_reopen freopen ! #ifdef SOCKS_64BIT_BUG ! # define PerlIO_close(f) (Perl_do_s64_delete_buffer(aTHX_ f)\, fclose(f)) ! #else ! # define PerlIO_close(f) fclose(f) ! #endif   #define PerlIO_puts(f\,s) fputs(s\,f)   #define PerlIO_putc(f\,c) fputc(c\,f)   #if defined(VMS) --- 18\,24 ----   #define PerlIO_open fopen   #define PerlIO_fdopen fdopen   #define PerlIO_reopen freopen ! #define PerlIO_close(f) fclose(f)   #define PerlIO_puts(f\,s) fputs(s\,f)   #define PerlIO_putc(f\,c) fputc(c\,f)   #if defined(VMS) *************** *** 47\,63 ****   (feof(f) ? 0 : (SSize_t)fread(buf\,1\,count\,f))   # define PerlIO_tell(f) ftell(f)   #else ! # ifdef SOCKS_64BIT_BUG ! # define PerlIO_getc(f) Perl_do_s64_getc(aTHX_ f) ! # define PerlIO_ungetc(f\,c) Perl_do_s64_ungetc(aTHX_ c\,f) ! # define PerlIO_read(f\,buf\,count) Perl_do_s64_fread(aTHX_ buf\,count\,f) ! # define PerlIO_tell(f) Perl_do_s64_tell(aTHX_ f) ! # else ! # define PerlIO_getc(f) getc(f) ! # define PerlIO_ungetc(f\,c) ungetc(c\,f) ! # define PerlIO_read(f\,buf\,count) (SSize_t)fread(buf\,1\,count\,f) ! # define PerlIO_tell(f) ftell(f) ! # endif /* SOCKS_64BIT_BUG */   #endif   #define PerlIO_eof(f) feof(f)   #define PerlIO_getname(f\,b) fgetname(f\,b) --- 43\,52 ----   (feof(f) ? 0 : (SSize_t)fread(buf\,1\,count\,f))   # define PerlIO_tell(f) ftell(f)   #else ! # define PerlIO_getc(f) getc(f) ! # define PerlIO_ungetc(f\,c) ungetc(c\,f) ! # define PerlIO_read(f\,buf\,count) (SSize_t)fread(buf\,1\,count\,f) ! # define PerlIO_tell(f) ftell(f)   #endif   #define PerlIO_eof(f) feof(f)   #define PerlIO_getname(f\,b) fgetname(f\,b) *************** *** 65\,79 ****   #define PerlIO_fileno(f) fileno(f)   #define PerlIO_clearerr(f) clearerr(f)   #define PerlIO_flush(f) Fflush(f) ! #ifdef SOCKS_64BIT_BUG ! # define PerlIO_seek(f\,o\,w) Perl_do_s64_seek(aTHX_ f\,o\,w)   #else ! # if defined(VMS) && !defined(__DECC) ! /* Old VAXC RTL doesn't reset EOF on seek; Perl folk seem to expect this */ ! # define PerlIO_seek(f\,o\,w) (((f) && (*f) && ((*f)->_flag &= ~_IOEOF))\,fseek(f\,o\,w)) ! # else ! # define PerlIO_seek(f\,o\,w) fseek(f\,o\,w) ! # endif   #endif   #ifdef HAS_FGETPOS   #define PerlIO_getpos(f\,p) fgetpos(f\,p) --- 54\,64 ----   #define PerlIO_fileno(f) fileno(f)   #define PerlIO_clearerr(f) clearerr(f)   #define PerlIO_flush(f) Fflush(f) ! #if defined(VMS) && !defined(__DECC) ! /* Old VAXC RTL doesn't reset EOF on seek; Perl folk seem to expect this */ ! #define PerlIO_seek(f\,o\,w) (((f) && (*f) && ((*f)->_flag &= ~_IOEOF))\,fseek(f\,o\,w))   #else ! # define PerlIO_seek(f\,o\,w) fseek(f\,o\,w)   #endif   #ifdef HAS_FGETPOS   #define PerlIO_getpos(f\,p) fgetpos(f\,p) *** ./doio.c.FCS Fri Nov 24 16​:05​:41 2000 --- ./doio.c Fri Nov 24 16​:14​:02 2000 *************** *** 2039\,2215 ****  
  #endif /* SYSV IPC */  
- #ifdef SOCKS_64BIT_BUG - - /** - ** getc and ungetc wrappers for the 64 bit problems with SOCKS 5 support - ** Workaround to the problem\, that SOCKS maps a socket 'getc' to revc - ** without checking the ungetc buffer. - **/ - - /* Not threadsafe? */ - static S64_IOB *s64_buffer = (S64_IOB *) NULL; - - /* initialize the buffer area */ - /* required after a fork(2) call in order to remove side effects */ - void - Perl_do_s64_init_buffer(void) - { - s64_buffer = (S64_IOB *) NULL; - } - - /* get a buffered stream pointer */ - STATIC S64_IOB* - S_s64_get_buffer(pTHX_ PerlIO *fp) - { - S64_IOB *ptr = s64_buffer; - while( ptr && ptr->fp != fp) - ptr = ptr->next; - return( ptr); - } - - /* create a buffered stream pointer */ - STATIC S64_IOB* - S_s64_create_buffer(pTHX_ PerlIO *f) - { - S64_IOB *ptr = malloc( sizeof( S64_IOB)); - if( ptr) { - ptr->fp = f; - ptr->cnt = ptr->size = 0; - ptr->buffer = (int *) NULL; - ptr->next = s64_buffer; - ptr->last = (S64_IOB *) NULL; - if( s64_buffer) s64_buffer->last = ptr; - s64_buffer = ptr; - } - return( ptr); - } - - /* delete a buffered stream pointer */ - void - Perl_do_s64_delete_buffer(pTHX_ PerlIO *f) - { - S64_IOB *ptr = S_s64_get_buffer(aTHX_ f); - if( ptr) { - /* fix the stream pointer according to the bytes buffered */ - /* required\, if this is called in a seek-context */ - if( ptr->cnt) fseek(f\,-ptr->cnt\,SEEK_CUR); - if( ptr->buffer) free( ptr->buffer); - if( ptr->last) - ptr->last->next = ptr->next; - else - s64_buffer = ptr->next; - free( ptr); - } - } - - /* internal buffer management */ - - #define S64_BUFFER_SIZE 32 - - STATIC int - S_s64_malloc(pTHX_ S64_IOB *ptr) - { - if( ptr) { - if( !ptr->buffer) { - ptr->buffer = (int *) calloc( S64_BUFFER_SIZE\, sizeof( int)); - ptr->size = ptr->cnt = 0; - } else { - ptr->buffer = (int *) realloc( ptr->buffer\, - ptr->size + S64_BUFFER_SIZE); - } -
- if( !ptr->buffer) - return( 0); -
- ptr->size += S64_BUFFER_SIZE; -
- return( 1); - } - - return( 0); - } - - /* SOCKS 64 bit getc replacement */ - int - Perl_do_s64_getc(pTHX_ PerlIO *f) - { - S64_IOB *ptr = S_s64_get_buffer(aTHX_ f); - if( ptr) { - if( ptr->cnt) - return( ptr->buffer[--ptr->cnt]); - } - return( getc(f)); - } - - /* SOCKS 64 bit ungetc replacement */ - int - Perl_do_s64_ungetc(pTHX_ int ch\, PerlIO *f) - { - S64_IOB *ptr = S_s64_get_buffer(aTHX_ f); - - if( !ptr) ptr = S_s64_create_buffer(aTHX_ f); - if( !ptr) return( EOF); - if( !ptr->buffer || (ptr->buffer && ptr->cnt >= ptr->size)) - if( !S_s64_malloc(aTHX_ ptr)) return( EOF); - ptr->buffer[ptr->cnt++] = ch; - - return( ch); - } - - /* SOCKS 64 bit fread replacement */ - SSize_t - Perl_do_s64_fread(pTHX_ void *buf\, SSize_t count\, PerlIO* f) - { - SSize_t len = 0; - char *bufptr = (char *) buf; - S64_IOB *ptr = S_s64_get_buffer(aTHX_ f); - if( ptr) { - while( ptr->cnt && count) { - *bufptr++ = ptr->buffer[--ptr->cnt]; - count--\, len++; - } - } - if( count) - len += (SSize_t)fread(bufptr\,1\,count\,f); - - return( len); - } - - /* SOCKS 64 bit fseek replacement */ - int - Perl_do_s64_seek(pTHX_ PerlIO* f\, Off_t offset\, int whence) - { - S64_IOB *ptr = S_s64_get_buffer(aTHX_ f); - - /* Simply clear the buffer and seek if the position is absolute */ - if( SEEK_SET == whence || SEEK_END == whence) { - if( ptr) ptr->cnt = 0; - - /* In case of relative positioning clear the buffer and calculate */ - /* a fixed offset */ - } else if( SEEK_CUR == whence) { - if( ptr) { - offset -= (Off_t)ptr->cnt; - ptr->cnt = 0; - } - } - - /* leave out buffer untouched otherwise\, because fseek will fail */ - /* seek now */ - return( fseeko( f\, offset\, whence)); - } - - /* SOCKS 64 bit ftell replacement */ - Off_t - Perl_do_s64_tell(pTHX_ PerlIO* f) - { - Off_t offset = 0; - S64_IOB *ptr = S_s64_get_buffer(aTHX_ f); - if( ptr) - offset = ptr->cnt; - return( ftello(f) - offset); - } - - #endif /* SOCKS_64BIT_BUG */ - --- 2039\,2041 ---- *** ./pp_sys.c.FCS Fri Nov 24 16​:05​:42 2000 --- ./pp_sys.c Fri Nov 24 16​:15​:39 2000 *************** *** 3732\,3740 ****   if (childpid \< 0)   RETSETUNDEF;   if (!childpid) { - #ifdef SOCKS_64BIT_BUG - Perl_do_s64_init_buffer(); - #endif   /*SUPPRESS 560*/   if ((tmpgv = gv_fetchpv("$"\, TRUE\, SVt_PV)))   sv_setiv(GvSV(tmpgv)\, (IV)PerlProc_getpid()); --- 3732\,3737 ---- *** perlio.c.FCS Fri Nov 24 17​:55​:38 2000 --- perlio.c Fri Nov 24 18​:01​:13 2000 *************** *** 1368\,1375 ****   IV   PerlIOStdio_close(PerlIO *f)   {   FILE *stdio = PerlIOSelf(f\,PerlIOStdio)->stdio; ! return fclose(stdio);   }  
  IV --- 1368\,1379 ----   IV   PerlIOStdio_close(PerlIO *f)   { + int optval\, optlen = sizeof(int);   FILE *stdio = PerlIOSelf(f\,PerlIOStdio)->stdio; ! return( ! (getsockopt(PerlIO_fileno(f)\, SOL_SOCKET\, SO_TYPE\, (char *)&optval\, &optlen) \< 0) ? ! fclose(stdio) : ! close(PerlIO_fileno(f)));   }  
  IV *** t/lib/io_sock.t.FCS Fri Nov 24 18​:08​:28 2000 --- t/lib/io_sock.t Fri Nov 24 18​:08​:48 2000 *************** *** 30\,36 ****   }  
  $| = 1; ! print "1..14\n";  
  use IO​::Socket;  
--- 30\,36 ----   }  
  $| = 1; ! print "1..20\n";  
  use IO​::Socket;  
*************** *** 203\,205 **** --- 203\,333 ----   $server->blocking(0);   print "not " if $server->blocking;   print "ok 14\n"; + + ### TEST 15 + ### Set up some data to be transfered between the server and + ### the client. We'll use own source code ... + # + local @​data; + if( !open( SRC\, "\< ../$0")) { + print "not ok 15 - $!"; + } else { + @​data = \; + close( SRC); + } + print "ok 15\n"; + + ### TEST 16 + ### Start the server + # + my $listen = IO​::Socket​::INET->new( Listen => 2\, Proto => 'tcp'\, Timeout => 15) || + print "not "; + print "ok 16\n"; + die if( !defined( $listen)); + my $serverport = $listen->sockport; + + my $server_pid = fork(); + if( $server_pid) { + + ### TEST 17 C/S establishment + # + print "ok 17\n"; + + ### TEST 18 + ### Get data from the server using a single stream + # + $sock = IO​::Socket​::INET->new("localhost​:$serverport") + || IO​::Socket​::INET->new("127.0.0.1​:$serverport"); + + if ($sock) { + $sock->print("send\n"); + + my @​array = (); + while( \<$sock>) { + push( @​array\, $_); + } + + $sock->print("done\n"); + $sock->close; + + print "not " if( @​array != @​data); + } else { + print "not "; + } + print "ok 18\n"; + + ### TEST 19 + ### Get data from the server using a stream\, which is + ### interrupted by eof calls. + ### On perl-5.7.0@​7673 this failed in a SOCKS environment\, because eof + ### did an getc followed by an ungetc in order to check for the streams + ### end. getc(3) got replaced by the SOCKS funktion\, which ended up in + ### a recv(2) call on the socket\, while ungetc(3) put back a character + ### to an IO buffer\, which never again was read. + # + $sock = IO​::Socket​::INET->new("localhost​:$serverport") + || IO​::Socket​::INET->new("127.0.0.1​:$serverport"); + + if ($sock) { + $sock->print("send\n"); + + my @​array = (); + while( !eof( $sock ) ){ + while( \<$sock>) { + push( @​array\, $_); + last; + } + } + + $sock->print("done\n"); + $sock->close; + + print "not " if( @​array != @​data); + } else { + print "not "; + } + print "ok 19\n"; + + ### TEST 20 + ### Stop the server + # + $sock = IO​::Socket​::INET->new("localhost​:$serverport") + || IO​::Socket​::INET->new("127.0.0.1​:$serverport"); + + if ($sock) { + $sock->print("done\n"); + $sock->close; + + print "not " if( 1 != kill 0\, $server_pid); + } else { + print "not "; + } + print "ok 20\n"; + + } elsif( defined( $server_pid)) { +
+ ### Child + # + SERVER_LOOP​: while (1) { + last SERVER_LOOP unless $sock = $listen->accept; + while (\<$sock>) { + last SERVER_LOOP if /^quit/; + last if /^done/; + if( /^send/) { + print $sock @​data; + last; + } + print; + } + $sock = undef; + } + $listen->close; + + } else { + + ### Fork failed + # + print "not ok 17\n"; + die; + } +

p5pRT commented 23 years ago

From @jhamisch

Hi\,

there is a little typo in the patch I've mailed. Apply this after the patch​:

*** t/lib/io_sock.t.FCS Fri Nov 24 18​:59​:14 2000 --- t/lib/io_sock.t Fri Nov 24 18​:58​:19 2000 *************** *** 209\,215 ****   ### the client. We'll use own source code ...   #   local @​data; ! if( !open( SRC\, "\< ../$0")) {   print "not ok 15 - $!";   } else {   @​data = \; --- 209\,215 ----   ### the client. We'll use own source code ...   #   local @​data; ! if( !open( SRC\, "\< $0")) {   print "not ok 15 - $!";   } else {   @​data = \;

BTW​: The test on Solaris 2.6 sparc were successfull!

-- Jens


  / +##+|##+ STRAWBERRY Jens Hamisch +v#+v v##+ EDV-Systeme GmbH Managing director / v v\v | . . . | Brauneckweg 2 Car (Voice)​: (+49 172) 81 04 162 | . | D-82549 Koenigsdorf Voice​: (+49 8179) 9305-50 | . | Fax​: (+49 8179) 9305-38 \ . / Tel./Fax​: (+49 8179) 9305-50 Email​: jens@​Strawberry.COM   \____/ Strawberry@​Strawberry.COM