1
votes

I am facing a design problem related to sockets and multi-threading.

Let the following things :

  • A stack of network protocols whose bottom layer is a socket layer using TCP/IP.

  • A "sender" thread that :

    • Performs the connection process (which involves sending and receiving data)

    • Once the connection is established, starts a "receiver" thread that receives data in the background.

    • Sends data.

    • When the application decides to exit, stops the receiver thread.

    • Performs the disconnection (which also involves sending and receiving data).

  • A "receiver" threads that receives the data during the data exchange phase, i.e between a connection and a disconnection.

My problem is that, when the sender thread wants to perform the disconnection process, it first needs to stop the receiver thread. Because the receiver thread is performing a blocking receive, the only way to stop it that I am aware of is to brutally close the socket. But doing so would prevent me from performing a clean disconnection because the disconnection process requires to send and receive data before closing the socket.

So my question is : is it possible to stop a blocking receive without closing the socket and if yes, how can I do it ? Or do I need to redesign my application ?

I could add a timeout to my blocking receive in order to periodically check whether to stop receiving, but it would feel not very responsive and seems to be a dirty approach.

I'm not bothering you with the full code because it works as intended and has dependencies. My receive is performed with a select() and then a recv() as follows :

iRes = select( 0, & fdRead, NULL, NULL, m_nTmout == 0 ? NULL : & tv );
...
iRes = recv( m_hSock, (char *) pBytes, nMaxLen, 0 );

This is Win32 code, but I also have something similar on Linux (Android to be more specific). In both case I'm using C and C++.

Thank you.

1
putting a timeout on the receiving thread's reads would only affect responsiveness at the point of exit - it should have negligible effect during normal running (albeit at a small cost of CPU used since the thread won't be completely blocked when it's not reading) - Alnitak
True, but there has to be a cleaner way, right ? - Virus721
I'm not sure there is, actually, at least not portably. The only way I know is to send a signal to each child thread so that the read in progress gets killed with an EINTR error code (on POSIX systems) - Alnitak
Ok thanks for your help. Unfortunately I'm not targetting only POSIX systems so I should maybe use the timeout approach. - Virus721
If disconnection process involves sending and receiving data(at application layer), can receiving thread not identify(by looking at received data) disconnection is initiated and it need to stop - Pras

1 Answers

0
votes

As you use select() for as blocking operation, you may create pipe() for passing commands from the sender to the receiver.

By adding read end of that pipe to the select() read list, you may be sure that any command written to that pipe will awoke the select() call. So receiver will be able to process this command.