socketssendlwip

(LwIP) socket send() returns "Connection already in progress"


I'm maintaining an embedded system that uses LwIP. The relevant code is as follows (edited):

iobSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connectRC = connect(socket, &serverAddress, sizeof(struct sockaddr));
FD_SET(socket, &fdset);
selectRC = select((socket) + 1, NULL, &fdset, NULL, &tv);
sendRC = send(iobSocket, dout, strlen(dout), 0);

This seems to work. When I remove the select() call, however, I get an error on the send() which sets errno to 119 or Connection already in progress. This error code isn't documented in the send() man pages.

Can someone tell me why the select() command is even necessary here, and why I might be getting an undocumented error without it?

Thank you.


Solution

  • Error code 119 is EINPROGRESS. It means the socket is operating in non-blocking mode 1, and the previous connect() operation hasn't finished yet, which is why the send() fails.

    1: Which means, there must be more code that you are not showing, as sockets are normally in blocking mode when they are initially created, and require explicit code to put them into non-blocking mode, such as via fcntl(F_SETFL, O_NONBLOCK);.

    Using select() to test the socket for writability allows your code to wait until the socket is actually done connecting and is ready for sending.

    This is explained in the man page for connect():

    RETURN VALUE

    If the connection or binding succeeds, zero is returned. On error, -1 is returned, and errno is set to indicate the error.

    ERRORS

    The following are general socket errors only. There may be other domain-specific error codes.

    ...

    EINPROGRESS
    The socket is nonblocking and the connection cannot be completed immediately. (UNIX domain sockets failed with EAGAIN instead.) It is possible to select(2) or poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure).