Subject: Cygwin 1.1.7: problems in select() under Win95/98/ME (was Possible problems in select()...)
From: "Vic Cross" <[email-masked]>
To: <[email-masked]>
Date: Fri, 2 Feb 2001 21:57:56 +1000

Corinna (and list):

Sorry it's taken a couple of days, my real job encroached on this project.
Enough of that.

Following is the testcase program.  Note that this is *just* the testcase,
hence the lack of the usual testing of return conditions on the socket
operations (I was in a hurry).  If you have UNIX Network Programming Volume
1 2nd Edition by W Richard Stevens, look to page 165 and you'll see the same
code (without the sleep() and printf() calls, included for testing).  The
code of our project is basically the same as this example.

For another example of code that exhibits the problem, have a look at
Cygwin's port of telnet; as per my original post part of the problem (the
TIME_WAIT connections) appears when using telnet.

Cygwin version is 1.1.7.

Thanks for the help,
Vic

******** BEGIN INCLUDED FILE **********
#define SA struct sockaddr
#define socklen_t int
#define SERV_PORT 9877
#define LISTENQ 1024

#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/select.h>
/* #include <sys/sockio.h> */

ssize_t
writen(int fd, const void *vptr, size_t n)
{
 size_t nleft;
 ssize_t nwritten;
 const char *ptr;

 ptr = vptr;
 nleft = n;
 while (nleft > 0) {
  if ((nwritten = write(fd, ptr, nleft)) <= 0) {
   if (errno == EINTR)
    nwritten = 0;
   else
    return (-1);
  }
  nleft -= nwritten;
  ptr += nwritten;
 }
 return (n);
}

ssize_t
readline(int fd, void *vptr, size_t maxlen)
{
 ssize_t n, rc;
 char c, *ptr;

 ptr = vptr;
 for (n = 1; n < maxlen; n++) {
  again:
  if ((rc = read(fd, &c, 1)) == 1) {
   *ptr++ = c;
   if (c == '\n')
    break;
  } else if (rc == 0) {
   if (n == 1)
    return (0);
   else
    break;
  } else {
   if (errno == EINTR)
    goto again;
   return (-1);
  }
 }

 *ptr = 0;
 return (n);
}

int
main(int argc, char **argv)
{
 int i, maxi, maxfd, listenfd, connfd, sockfd;
 int nready, client[FD_SETSIZE];
 ssize_t n;
 fd_set rset, allset;
 char line[80];
 socklen_t clilen;
 struct sockaddr_in cliaddr, servaddr;

 listenfd = socket(AF_INET, SOCK_STREAM, 0);
 bzero((void *) &servaddr, sizeof(servaddr));
 servaddr.sin_family = AF_INET;
 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
 servaddr.sin_port = htons(SERV_PORT);

 bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

 listen(listenfd, LISTENQ);

 maxfd = listenfd;
 maxi = -1;

 for (i = 0; i < FD_SETSIZE; i++)
   client[i] = -1;

 printf("Calling FD_ZERO...\n");
 FD_ZERO(&allset);
 printf("Calling FD_SET...\n");
 FD_SET(listenfd, &allset);
 printf("Out of FD_SET...\n");

 for ( ; ; ) {
  rset = allset;
  printf("Entering select()... \n");
  nready = select(maxfd+1, &rset, NULL, NULL, NULL);
  printf("Select unblocked, sleeping for 5... \n");
  sleep(5);
  printf("ok, checking now.\n");

  if (FD_ISSET(listenfd, &rset)) {
   clilen = sizeof(cliaddr);
   connfd = accept(listenfd, (SA *) &cliaddr, &clilen);

   for (i = 0; i < FD_SETSIZE; i++)
    if (client[i] < 0) {
     client[i] = connfd;
     break;
    }

   FD_SET(connfd, &allset);
   if (connfd > maxfd)
    maxfd = connfd;
   if (i > maxi)
    maxi = i;

   if (--nready <= 0)
    continue;
  }
  for (i = 0; i <= maxi; i++) {
   if ((sockfd = client[i]) < 0)
    continue;
   if (FD_ISSET(sockfd, &rset)) {
    if ((n=readline(sockfd, line, 80)) == 0) {
     close(sockfd);
     FD_CLR(sockfd, &allset);
     client[i] = -1;
    } else
     writen(sockfd, line, n);

    if (--nready <= 0)
     break;
   }
  }
 }
}
********* END INCLUDED FILE ************

--
Want to unsubscribe from this list?
Check out: http://cygwin.com/ml/#unsubscribe-simple