how to interrupt a thread which is waiting on recv function?

10,972

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.

Share:
10,972

Related videos on Youtube

MCA
Author by

MCA

Updated on June 04, 2022

Comments

  • MCA
    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
    Remy Lebeau almost 12 years
    You don't need to put the socket into non-blocking mode in order to use select(). You can use select() with blocking sockets. Just call select() to make sure the socket is readable before before calling recv(), then `recv() will not block even if the socket is in blocking mode.
  • paulm
    paulm almost 11 years
    call closesocket() in the APC call and it will return, no need for async socket or evil TerminateThread calls :)
  • rogerdpack
    rogerdpack over 10 years
    Just 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
    Jeremy Friesner over 10 years
    I'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
    Jeremy Friesner over 10 years
    Also, the check-with-select-before-recv() approach doesn't always work reliably: stackoverflow.com/a/5352634/131930
  • rogerdpack
    rogerdpack over 10 years
    re: async apparently that is possible using WaitForMultipleObjects ffmpeg.org/pipermail/ffmpeg-devel/2013-December/152211.html
  • Remy Lebeau
    Remy Lebeau over 10 years
    You cannot use any of the WaitFor...Object(s) functions with socket handles. You would have to use event handles from CreateEvent() instead, calling SetEvent() when socket operations complete. Or use WSACreateEvent() with WSAEventSelect() and WSAWaitForMultipleEvents(). Or use CreateIoCompletionPort() with GetQueuedCompletionStatus().
  • Tomer W
    Tomer W over 7 years
    terminate 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.

Related