[comp.unix.ultrix] Ultrix 4.1 connect

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/13/91)

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);
}

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/18/91)

In article <26530:Jun1218:54:1991@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> 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.

Perhaps I wasn't clear enough the first time.

Is DEC going to fix this bug before the end of the millenium? Has it, by
any chance, already been fixed in 4.2? (I doubt it, considering DEC's
track record. No offense intended---few companies do any better.)

---Dan