9

I am using Apache thrift in C++ on Windows and I would like to ask for your help with cancellation of a blocking read operation that is in progress. The read operation (for example – TProtocol::readByte) is blocked until the data is received. When I close the transport from another thread, I get a failed assertion about a null pointer.

Is there any other way to cancel a blocked read operation?

Alex Shtoff
  • 2,520
  • 1
  • 25
  • 53

2 Answers2

5

Assuming you are running on Windows (according to the tags on your question): You can cancel a blocking socket operation with WSACancelBlockingCall (although this operation is deprecated, it should still work). Your socket will then return the error code WSAEINTR (Interrupted function call) instead of WSAETIMEDOUT.

In Thrift, you can use TSocket::getSocketFD() or TPipe::getPipeHandle() to get the according handle for canceling the current operation.

stefan.schwetschke
  • 8,862
  • 1
  • 26
  • 30
  • Unfortunately, WSACancelBlockingCall has been removed from Winsock2. And Thrift uses Winsock2 (http://msdn.microsoft.com/en-us/library/windows/desktop/ms741547%28v=vs.85%29.aspx). But it is a nice idea. – Alex Shtoff Sep 10 '13 at 08:14
  • You can use the function, it is still there in Winsock2 (although it is not exported by the DLL). If you don't want to use such a hack, you can also close the socket from another thread. The blocking operation will get the error WSA_OPERATION_ABORTED (works for Winsock2 operations, but NOT for Winsock1 operations). – stefan.schwetschke Sep 10 '13 at 11:38
3

if you're using blocking mode, so the only option to abort the read operation is set a timeout on the TSocket before read it.

secmask
  • 7,649
  • 5
  • 35
  • 52
  • In this case, any implementation of TProtocol will not be able to differentiate between "the server has not sent data yet" and "the user wants to cancel the operation". As we do not operate over a fast connection, we really need to differentiate between those two cases. – Alex Shtoff Aug 29 '13 at 11:54
  • Why do you care about TProtocol? There will be a TimeoutException throw for both of case after the RPC call, and you can decide what to next. – secmask Aug 29 '13 at 13:32
  • Because the user of our communication code will get this exception in the *legitimate* case where the server's response has not arrived yet. If my timeout is too long, the response of the cancellation will be too slow for our client. As we operate in a low bandwidth and high latency environment, we cannot afford short timeouts as they will almost always happen. However, we still want to cancel. – Alex Shtoff Aug 29 '13 at 13:42
  • a dirty way is wrap this RPC a loop with acceptable timeout value, check the flag to see if user cancel the operation. Otherwise, you will have to switch to non-blocking way. – secmask Aug 29 '13 at 13:50