This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: bug in 1.3.3 2000/NT (probably socket())



On Oct 18, Christopher Faylor <cgf at redhat dot com> wrote:

> >The program works correctly under Cygwin 1.3.2 (NT and 2000) but not
> >under Cygwin 1.3.3 (NT or 2000). (It also works under Solaris 5.8).
> >Under 1.3.3, select() returns an error each time it is called:
> >
> >       select(): bad file number
> 
> Try a snapshot.
> 
> cgf

As requested, we tried running the test server program (as well as our
real software suite from which the test is culled) on both the 10/16
and 10/18 snapshots, but without success.

I append our original e-mail containing a description of the problem
and the test program.

Eric

****************************************************************************

To: cygwin@cygwin.com
Subject: bug in 1.3.3 2000/NT (probably socket())
cc: eric
Date: Thu, 18 Oct 2001 15:55:29 -0400
From: Eric Mandel <eric@head-cfa.harvard.edu>
Content-Length: 5548


Dear Cygwin Developer(s),

The appended test server program indicates a possible bug in one of
the socket routines under Cygwin 1.3.3. The program creates a socket,
listens for connections, accepts each connection, reads data from the
connected socket, and writes that data to stdout (i.e., an echo server).

The program works correctly under Cygwin 1.3.2 (NT and 2000) but not
under Cygwin 1.3.3 (NT or 2000). (It also works under Solaris 5.8).
Under 1.3.3, select() returns an error each time it is called:

	select(): bad file number

Thus, no accept is ever completed and no data is read or written.

However, it is unclear whether select() actually is the problem. A
short program that simply performs the socket() call indicates that
this latter call is destroying the heap. To see this, we debugged the
short program using gdb:

$ gdb -nw ./foo
GNU gdb 5.0 (20010428-1)
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-cygwin"...
(gdb) list
1       #include <stdio.h>
2       #include <sys/socket.h>
3       int main(int argc, char **argv)
4       {
5         int sock;
6         sock = socket(AF_INET, SOCK_STREAM, 0);
7         fprintf(stderr, "sock: %d\n");
8         if( sock <0 )
9           perror("socket");
10      }
(gdb) break main
Breakpoint 1 at 0x40105e: file foo.c, line 4.
(gdb) run
Starting program: /home/joye/eric/xpa-2.1.0b5/./foo.exe

Breakpoint 1, main (argc=1, argv=0xa011128) at foo.c:4
4       {
(gdb) n
6         sock = socket(AF_INET, SOCK_STREAM, 0);
(gdb) n
warning: HEAP[foo.exe]:
warning: Heap block at 0023E3F8 modified at 0023E65A past requested size of 25

Program received signal SIGTRAP, Trace/breakpoint trap.
0x77f9eeaa in ?? ()
(gdb) print/x  0x23e65a - 0x23e3f8
$1 = 0x262
(gdb) where
#0  0x77f9eeaa in ?? ()
#1  0x77fcd942 in ?? ()
#2  0x77fb54c9 in ?? ()
#3  0x77fb4316 in ?? ()
#4  0x77fab4ab in ?? ()
#5  0x778834e2 in _libkernel32_a_iname ()
#6  0x77883019 in _libkernel32_a_iname ()
#7  0x77882ce7 in _libkernel32_a_iname ()
#8  0x77882b69 in _libkernel32_a_iname ()
#9  0x77f8bfcc in ?? ()
#10 0x77f8c618 in ?? ()
#11 0x77f889c0 in ?? ()
#12 0x77e87270 in _libkernel32_a_iname ()
#13 0x75033803 in _libkernel32_a_iname ()
#14 0x75033700 in _libkernel32_a_iname ()
#15 0x00000001 in ?? ()
(gdb) quit
The program is running.  Exit anyway? (y or n) y

>From this evidence, it would appear that socket() might be writing 8
bytes more than it ought to into the heap.  We very much would
appreciate any help we can get in solving this problem -- and in turn
will offer any help you might require of us in this matter.

Regards,

Eric Mandel

/* ************************** foo.c ************************************** */

/* 
   To compile:
     gcc -g -o foo foo.c (for Sun Solaris add: -lsocket)

   To Run:

     # start server
     window1: ./foo
     (waits for connect and then reads from socket and writes to stdout)

     # connect using telnet client in another window
     window2: telnet localhost 1234
     (type characters and they should echo on the foo server machine)
or
     # can also use hostname ...
     window2: telnet <hostname> 1234
     (type characters and they should echo on the foo server machine)
*/

#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define SZ_BUF 		1024
#define PORT   		1234
#define MAXLISTEN	100

int main(int argc, char **argv)
{
  char buf[SZ_BUF];
  int got;
  int sock;
  int sock2;
  int width;
  int slen;
  int get=SZ_BUF-1;
  int reuse_addr=1;
  int keep_alive=1;
  fd_set readfds;
  struct sockaddr_in sock_in;
  struct sockaddr_in sock_in2;

  /* create socket */
  if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ){
    perror("socket");
    exit(1);
  }
  setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
	     (char *)&keep_alive, sizeof(keep_alive));
  memset((char *)&sock_in, 0, sizeof(sock_in));
  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
	     (char *)&reuse_addr, sizeof(reuse_addr));
  sock_in.sin_family = AF_INET;
  sock_in.sin_addr.s_addr = htonl(INADDR_ANY);
  sock_in.sin_port = htons(PORT);

  /* bind to a port */
  if( bind(sock, (struct sockaddr *)&sock_in, sizeof(sock_in)) < 0 ){
    perror("bind()");
    exit(1);
  }

  /* listen for connections */
  if( listen(sock, MAXLISTEN) < 0 ){
    perror("listen()");
    exit(1);
  }

  /* make sure we close on exec */
  fcntl(sock, F_SETFD, FD_CLOEXEC);

  /* init select parameters */
  width = getdtablesize();

  /* enter processing loop */
  while( 1 ){
    /* re-initialize select flags */
    FD_ZERO(&readfds);
    FD_SET(sock, &readfds);
    /* wait for next request */
    if( select(width, &readfds, NULL, NULL, NULL) > 0 ){
      /* process request */
      if( FD_ISSET(sock, &readfds) ){
	slen = sizeof(struct sockaddr_in);
	/* accept new connection */
	if( (sock2=accept(sock, (struct sockaddr *)&sock_in2, &slen)) >=0 ){
	  /* make sure we close on exec */
	  fcntl(sock2, F_SETFD, FD_CLOEXEC);
	  /* echo to stdout */
	  while( (got = recv(sock2, buf, get, 0)) > 0 )
	    write(1, buf, got);
	  close(sock2);
	}
      }
    }
    /* UNDER CYGWIN 1.3.3, THIS ERROR HAPPENS IMMEDIATELY */
    else{
      perror("select()");
      exit(1);
    }
  }
}

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]