Ultrix 4.1 connect() failure on FNDELAY socket behaves incorrectly

Dan Bernstein brnstnd at kramden.acf.nyu.edu
Thu Jun 13 04:54:19 AEST 1991


The enclosed program creates a stream socket, fcntl()s it to FNDELAY,
attempts to connect() to a nonexistent address, and select()s the socket
for writing. On any sane BSD machine, the select returns almost
immediately, as does a straight connect(): the network is unreachable.

Under Ultrix 4.1, a straight connect() fails almost immediately, but the
select() for writing hangs for 75 seconds. That's an awfully long time
to figure out that a net doesn't exist.

Who dreamed up this asinine behavior? (Probably the same person who
thought that if you select() a server socket for reading, accept() will
always succeed, even if you're out of file descriptors. In reality, the
accept() fails, and this person blithely continues to select()-accept()
and fill up people's error logs, as was noted here recently. [sigh])

---Dan

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
extern int errno;

main()
{
 int s;
 char *c;
 struct sockaddr_in sa;
 int fl;
 int r;
 fd_set rfds;
 fd_set wfds;
 fd_set efds;
 int now;

 s = socket(AF_INET,SOCK_STREAM,0);
 printf("socket %d\n",s);
 sa.sin_family = AF_INET;
 sa.sin_port = ntohs(21);
 c = (char *) &(sa.sin_addr);
 c[0] = 1; c[1] = 2; c[2] = 3; c[3] = 4;
 printf("address %s\n",inet_ntoa(sa.sin_addr));
 printf("getfl originally %d\n",fl = fcntl(s,F_GETFL,0));
 fcntl(s,F_SETFL,fl | FNDELAY);
 printf("getfl now %d\n",fl = fcntl(s,F_GETFL,0));
 r = connect(s,&sa,sizeof(sa));
 if (r == -1)
   if ((errno == EINPROGRESS) || (errno == EWOULDBLOCK))
    {
     perror("connect failed, known error");
     FD_ZERO(&rfds);
     FD_ZERO(&wfds);
     FD_ZERO(&efds);
     FD_SET(s,&wfds);
     time(&now);
     printf("select started %s",ctime(&now));
     printf("select returned %d\n"
       ,select(s + 1,&rfds,&wfds,&efds,(struct timeval *) 0));
     time(&now);
     printf("select finished %s",ctime(&now));
     printf("socket writable: %d\n",!!FD_ISSET(s,&wfds));
     /* if connection failed, will find out on first I/O */
    }
   else
     perror("connect failed, unrecognized error");
 else
   printf("connect succeeded immediately\n");
 exit(0);
}



More information about the Comp.unix.ultrix mailing list