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