: In our department we developed a communication component which was designed
: to use sockets as its basic mechanism for interprocess communication.
: In the select() system call we encountered serious problems causing
: the application to block in unpredictable situations.
: This behaviour occurs when trying to multiplex several socket-ports with select(). All sockets
: in the fd_set are registered for detecting read-events. After trying to find out why the select()-call
: blocks, we came to the conclusion that the implementation of select() itself causes the problems.
The semantics of socket + connect + select are a bit copmplicated and
it's sure worth to have a look at your specific implementation's man
pages. As a working example, it might be useful to peek at the source
of Mosaic-2.4 (.../libwww2/HTTCP.c):
/* Now, let's get a socket set up from the server for the data: */
*s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/*
* Make the socket non-blocking, so the connect can be canceled.
* This means that when we issue the connect we should NOT
* have to wait for the accept on the other end.
*/
[...]
ret = ioctl(*s, FIONBIO, &val);
[...]
/*
* Issue the connect. Since the server can't do an instantaneous accept
* and we are non-blocking, this will almost certainly return a negative
* status.
*/
status = connect(*s, (struct sockaddr*)&soc_address, sizeof(soc_address));
/*
* According to the Sun man page for connect:
* EINPROGRESS The socket is non-blocking and the con-
* nection cannot be completed immediately.
* It is possible to select(2) for comple-
* tion by selecting the socket for writ-
* ing.
* According to the Motorola SVR4 man page for connect:
* EAGAIN The socket is non-blocking and the con-
* nection cannot be completed immediately.
* It is possible to select for completion
* by selecting the socket for writing.
* However, this is only possible if the
* socket STREAMS module is the topmost
* module on the protocol stack with a
* write service procedure. This will be
* the normal case.
*/
#ifdef SVR4
if ((status < 0) && ((errno == EINPROGRESS)||(errno == EAGAIN)))
#else
if ((status < 0) && (errno == EINPROGRESS))
#endif /* SVR4 */
{
[...]
{
fd_set writefds;
int intr;
FD_ZERO(&writefds);
FD_SET(*s, &writefds);
#ifdef __hpux
ret = select(FD_SETSIZE, NULL, (int *)&writefds, NULL, &timeout);
#else
ret = select(FD_SETSIZE, NULL, &writefds, NULL, &timeout);
#endif
/*
* Again according to the Sun and Motorola man page for connect:
* EALREADY The socket is non-blocking and a previ-
* ous connection attempt has not yet been
* completed.
* Thus if the errno is NOT EALREADY we have a real error, and
* should break out here and return that error.
* Otherwise if it is EALREADY keep on trying to complete the
* connection.
*/
if ((ret < 0)&&(errno != EALREADY)
#ifdef SNI /* BUG in SINIX-D SVR4 */
&&(errno != EINPROGRESS)
#endif
[...]
)
--
#include <std/dsclm.h> /* SNI SU BS2000 SD124 - Muenchen, W. Germany */
______________
/\ _____________\
\ \ \__________ /
==============================\ \ \ / / /===============================
Linux - the U*ix of choice! \ \ \ / / / Linux is a * Un*x clone
\ \ \ / / / for 386/486, and it's FREE!!
Everything you ever wanted, \ \ \/ / /
and more, too! \ \ \/ / *** Read comp.os.linux ***
===================================\ \ /====================================
\_\/