Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Message-ID: <3EE106A9.2080200@ixiacom.com> Date: Fri, 06 Jun 2003 14:24:57 -0700 From: Dan Kegel User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020615 Debian/1.0.0-3 MIME-Version: 1.0 To: cygwin Subject: poll crashes with > 1200 fds Content-Type: multipart/mixed; boundary="------------090005080803070301010304" --------------090005080803070301010304 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit It looks like poll() is implemented on top of select() in cygwin. This is fine unless you try to use it in a program with more than 1024 fd's or so. Here's the result of running a test app that goes beyond that limit: Program received signal SIGSEGV, Segmentation fault. 0x6106fe3a in select () from /usr/bin/cygwin1.dll (gdb) bt #0 0x6106fe3a in select () from /usr/bin/cygwin1.dll #1 0x61610790 in ?? () #2 0x6106ca1d in select () from /usr/bin/cygwin1.dll #3 0x6106c223 in select () from /usr/bin/cygwin1.dll #4 0x61059e7d in poll () from /usr/bin/cygwin1.dll #5 0x004012d3 in count_connects (ipadr=16777343, portnum=80, want=1200) at pollbug.c:120 #6 0x0040175d in main (argc=2, argv=0xa0418c8) at pollbug.c:211 And here's the test code. To reproduce the bug, just run with argument 1500 or so. - Dan --------------090005080803070301010304 Content-Type: text/x-csrc; name="pollbug.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pollbug.c" /*-------------------------------------------------------------------------- Copyright 1999,2000, Dan Kegel http://www.kegel.com/ See the file COPYING This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------- Program to measure limits on network sockets, file descriptors, etc. --------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX #endif #define MAX_TEST 100000 int fds[MAX_TEST]; /*---------------------------------------------------------------------- Portable function to set a socket into nonblocking mode. ----------------------------------------------------------------------*/ static int setNonblocking(int fd) { int flags; /* Caution: O_NONBLOCK is defined but broken on SunOS 4.1.x and AIX 3.2.5. */ #if defined(O_NONBLOCK) if (-1 == (flags = fcntl(fd, F_GETFL, 0))) flags = 0; return fcntl(fd, F_SETFL, flags | O_NONBLOCK); #else flags = 1; return ioctl(fd, FIOBIO, &flags); #endif } static int count_connects(int ipadr, int portnum, int want) { int i; int maxfd; int nopen; struct pollfd pfds[MAX_TEST]; int nok; int nrej; time_t end; #ifdef VERBOSE printf("Starting connections until we can't start any more; will print what stops us to stderr.\n"); #endif for (i = 0; i < want; i++) { struct sockaddr_in srv_addr; int err; fds[i] = socket(AF_INET, SOCK_STREAM, 0); if (fds[i] < 0) { #ifdef VERBOSE perror("socket"); #endif break; } setNonblocking(fds[i]); /* else connect will wait until resources avail */ memset((char *) &srv_addr, 0, sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_addr.s_addr = ipadr; srv_addr.sin_port = htons(portnum); err = connect(fds[i], (struct sockaddr *) &srv_addr, sizeof(srv_addr)); if ((err != 0) && (errno != EINPROGRESS)) { #ifdef VERBOSE perror("connect"); #endif break; } pfds[i].fd = fds[i]; pfds[i].events = POLLOUT; } maxfd = i; #ifdef VERBOSE printf("%d connections in progress...\n", maxfd); #endif /* Now sit until they all connect or fail, or until five seconds * pass, whichever comes first. */ end = time(0) + 6; for (nrej=nok=0, nopen=maxfd; nopen; ) { int nready; if ((end - time(0)) < 0) break; nready = poll(pfds, maxfd, 1000); if (nready < 0) { perror("poll"); exit(1); } for (i=0; i MAX_TEST) { printf("Sorry, want must be between 1 and %d\n", MAX_TEST); exit(1); } if (argc < 3) ipadrstr = "127.0.0.1"; else ipadrstr = argv[2]; ipadr = inet_addr(ipadrstr); if (ipadr == -1) { printf("Bad ip address %s.\n", ipadrstr); exit(1); } if (argc < 4) portnum = 80; else { const char *portnumstr; portnumstr = argv[3]; portnum = atoi(portnumstr); if ((portnum <= 0) || (portnum > 65535)) { printf("Bad port number '%s'. Must be number between 1 and 65535.\n", portnumstr); exit(1); } } printf("Can start %d nonblocking connect()'s\n", count_connects(ipadr, portnum, want)); return 0; } --------------090005080803070301010304 Content-Type: text/plain; charset=us-ascii -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/ --------------090005080803070301010304--