views:

71

answers:

1

I have tracked down a deadlock in some code of mine using this reproducer:

if( isClient )
{
    Sender sender;
    Receiver receiver;
    ConnectionPtr connection = Connection::create( description );
    TEST( connection->connect( ));

    receiver.start();
    Sleep( 100 );
    sender.start();

    sender.join();
}
else
{
    ConnectionPtr connection = Connection::create( description );
    TEST( connection->listen( ));

    Sender sender;
    Receiver receiver;
    ConnectionPtr reader = connection->accept();

    receiver.start();
    Sleep( 100 );
    sender.start();

    receiver.join();
}

I start on the same machine a server and then a client process on 127.0.0.1:1234. Both deadlock immediately in ::recv and ::send. Sender and Receiver are separate threads executing send/recv in a loop. The sockets are blocking, BSD-style TCP sockets.

When I change the order of operations to start the Sender before the Receivers, it works.

Why?

A: 

In your example if peer1 is not reading data a peer2 will block in send after socket send buffer is full.

Usually deadlock can occur if you have some kind of a protocol and server fails to read message part while client is waiting for response.

Generally to debug this kind of problems verbose logging is introduced both on client and server sides. And when the problem occurs you can analyze logs and see what went wrong.

Vadmyst
In my examples both ends have a send and a recv thread. Both send and receive continously unstructured data, which they don't parse at all.Imo no deadlock should occur in this setup, and none does on Unix systems.
eile