Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!thunder.mcrcim.mcgill.edu!snorkelwacker.mit.edu!spool.mu.edu!caen!zaphod.mps.ohio-state.edu!swrinde!elroy.jpl.nasa.gov!ncar!hsdndev!cmcl2!kramden.acf.nyu.edu!brnstnd From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein) Newsgroups: comp.unix.ultrix Subject: Ultrix 4.1 connect() failure on FNDELAY socket behaves incorrectly Message-ID: <26530:Jun1218:54:1991@kramden.acf.nyu.edu> Date: 12 Jun 91 18:54:19 GMT Organization: IR Lines: 73 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 #include #include #include #include #include #include #include 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); }