InterprocessConnection teardown when connection is abruptly cut

I have a client/server with InterprocessConnection on both sides using a socket between them over a WAN. They use sendMessage and messageReceived like normal. If the connection between them is torn down abnormally, I hit a race condition. Let’s say one side has it’s ethernet cable removed abruptly. What I see is that one or both sides get stuck in sendMessage()->writeMessage() waiting for the outgoing data to get acknowledged by the other side. This locks pipeAndSocketLock. Meanwhile, I detect that the other side is gone at the application level because I have a ping going on. So, my application attempts to tear things down by calling disconnect(), but then gets stuck waiting on pipeAndSocketLock and things freeze up.

I would expect that disconnect() would call socket->close() unconditionally, and then maybe that would cause the blocked socket->send() call to return and error out (?). I could force this by accessing the getSocket()->close() to get around pipeAndSocketLock, but…I’m not confident about this. The internet seems to be saying that I need an asynchronous send(), which I doubt is planned for JUCE.

It appears that this works when I detect that the connection is dead. The detecting thread (Message thread in this case) can do this inside the InterprocessConnection class:

   if (getSocket()->getRawSocketHandle() >= 0)
        ::close(getSocket()->getRawSocketHandle());
    disconnect();

The socket close will cause sendMessage to unblock in the send thread. The send thread looks like this:

    if (!sendMessage(data))
    {
        disconnect();
    }

Might cause multiple calls to disconnect in this specific case, but seems safe and seems to work.