how to interrupt a thread which is waiting on recv function?
Solution 1
You can interrupt it by queuing an APC to it via QueueUserAPC
. However, it's most likely unsafe to terminate the thread in the APC. Queuing an APC doesn't end the recv
, it just interrupts it; once the APC returns, it will go back to waiting on recv
again.
If you want to stop the recv
completely, you should be using select
with a timeout to wait until data is available. You can then check whether you should keep waiting for data or continue at each timeout.
Solution 2
If you don't want to receive any more data, you can kill the socket at anytime. Just call close() on it, the function in question will immediately return an error.
What I've done in the past is just run another thread with a timeout, after the waiting period if a "don't die" flag isn't set kill the socket.
Solution 3
Checking the socket buffer prior to recv
is more flexible rather than covering a lot for select()
support, I think. You can call ioctlsocket(SockHandle, FIONREAD, Longint(CountInBuffer))
to see if there's data in network buffer to read and then call recv(SockHandle, buff, CountInBuffer, 0)
. This way you can make a single recv call to read the whole network read buffer if you allocate the buff itself enough with CountInBuffer. Otherwise, you need to call recv in a loop to read the network buffer, which is the traditional way. In both cases, you're still in the constraints of the CountInBuffer
.
Related videos on Youtube
MCA
Updated on June 04, 2022Comments
-
MCA almost 2 years
I have a socket listener which hangs on recv function:
size_t recvLen = recv(sock, buf, 512, 0);
I would like to terminate this thread with interrupting it. MSDN says:
When issuing a blocking Winsock call such as recv, Winsock may need to wait for a network event before the call can complete. Winsock performs an alertable wait in this situation, which can be interrupted by an asynchronous procedure call (APC) scheduled on the same thread.
How can I do that?
-
Remy Lebeau almost 12 yearsYou don't need to put the socket into non-blocking mode in order to use
select()
. You can useselect()
with blocking sockets. Just callselect()
to make sure the socket is readable before before callingrecv()
, then `recv() will not block even if the socket is in blocking mode. -
paulm almost 11 yearscall closesocket() in the APC call and it will return, no need for async socket or evil TerminateThread calls :)
-
rogerdpack over 10 yearsJust make sure you don't have a race condition where the other thread could have closed it for you already, or you may be closing a socket descriptor opened for some other socket (a new socket) already [?]
-
Jeremy Friesner over 10 yearsI'm not sure how that is any easier/better than putting the socket into non-blocking mode. Now instead of adding one line of code, you have to add one line of code before every potentially-blocking call to the socket (and if you, or future code maintainers, ever forget to do so, you will have a subtle and hard-to-detect bug in your program that might cost someone a lot of time to track down)
-
Jeremy Friesner over 10 yearsAlso, the check-with-select-before-recv() approach doesn't always work reliably: stackoverflow.com/a/5352634/131930
-
rogerdpack over 10 yearsre: async apparently that is possible using WaitForMultipleObjects ffmpeg.org/pipermail/ffmpeg-devel/2013-December/152211.html
-
Remy Lebeau over 10 yearsYou cannot use any of the
WaitFor...Object(s)
functions with socket handles. You would have to use event handles fromCreateEvent()
instead, callingSetEvent()
when socket operations complete. Or useWSACreateEvent()
withWSAEventSelect()
andWSAWaitForMultipleEvents()
. Or useCreateIoCompletionPort()
withGetQueuedCompletionStatus()
. -
Tomer W over 7 yearsterminate thread should not be used as it doesnt notify DLLs and does not let the thread to cleanup. Closing the socket is possible, but you might still need the socket.