Sockets end in state eCLOSE_WAIT

Hi @oberondoro, thank you for reporting this.

You should be able to post links by now.

We are not aware that the +TCP library has or had a problem with “hanging sockets”.

Somewhere in the code I read:

  /* And wait for the user to close this socket. */
     vTCPStateChange( pxSocket, eCLOSE_WAIT );

Which says that the eCLOSE_WAIT state must be handled by the owner of the socket.

@oberondoro wrote:

Is there another way to safely close these sockets or another way to solve the problem?
Can I directly check the socket state and close it if “eCLOSE_WAIT”?

Yes, if you are sure that the socket won’t be referred to by your application or by the HTTP library, you can call closesocket() to delete the socket.

Here below I will describe how this normally happens:

When a TCP API returns a negative number, it contains an errno value.

Most negative codes are fatal errors, except for pdFREERTOS_ERRNO_EAGAIN (AKA pdFREERTOS_ERRNO_EWOULDBLOCK) and pdFREERTOS_ERRNO_EINTR.

This is a simple TCP echo server:

    for( ;; )
    {
        BaseType_t xRc = FreeRTOS_recv( xSocket, pcBuffer, sizeof pcBuffer, 0 );
        if( xRc > 0 )
        {
            xRc = FreeRTOS_send( xSocket, pcBuffer, ( size_t ) xRc, 0 );
        }
        if( xRc < 0 )
        {
            if( ( xRc != -pdFREERTOS_ERRNO_EAGAIN ) &&
                ( xRc != -pdFREERTOS_ERRNO_EINTR ) )
            {
                printf("The connection is broken with errno %d\n", -xRc );
                break;
            }
        }
    }
    /* The socket will be deleted. */
    FreeRTOS_closesocket( xSocket );

Note that in the above example there is no need to call shutdown(). The peer already took the initiative to shutdown the connection.

Some users are confused about the use of shutdown(). HTTP servers are usually passive, they will only close a socket when the connection got disrupted, as in the above example.

I am not sure who is responsible to close a connection when using REST-API, but if you need to close a connection actively (and gracefully), the following can be done:

    /* Start closing the connection: */
    FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );
    for( ;; )
    {
        BaseType_t xRc = FreeRTOS_recv( xSocket, pcBuffer, sizeof pcBuffer, 0 );
        if( xRc > 0 )
        {
            /* Very important: handle the last bytes received. */
        }
        else if( xRc < 0 )
        {
            if( ( xRc != -pdFREERTOS_ERRNO_EAGAIN ) &&
                ( xRc != -pdFREERTOS_ERRNO_EINTR ) )
            {
                printf("The shutdown is acknowledged by the peer (errno %d)\n", -xRc );
                break;
            }
        }
    }
    /* Close ( free ) the socket. */
    FreeRTOS_closesocket( xSocket );

In other words, call shutdown() once, wait until an API call (like recv() returns a fatal code, and close the socket.