0

Trying to stop IOCP worker thread and close socket and related per io datums This is based on reference counting and when ref count reach 0, close socket and delete buffers. Below is skeleton of IOCP worker thread. When I want to stop IO , call 'FFT_stop_session' function. which just 'PostQueuedCompletion.." This way seems to work. but crash happens times to times..error message like below..

"HEAP: Free Heap block ??? modified at ??? after it was freed"

But I can't understand why double free can be happened ???

static unsigned int WINAPI FFT_thread_worker (LPVOID param)
{
        ...
    while(fft->running==TRUE)
    {
        iostatus = GetQueuedCompletionStatus(fft->hIOCP,&byteio,&completion_key (LPOVERLAPPED*)&ovlp,INFINITE);
        if(iostatus == TRUE)
        {
            fftsock  = (FFTSOCKET*)ovlp;
            ffts     = fftsock->session;

            switch(completion_key)
            {
                //-- S E N D
                case FFT_SEND:
                {                   
                                        // io works here                                         
                    FFTSOCKET_ref_inc(fftsock);
                    FFTSOCKET_send(fftsock,&byteio);                    
                    break;
                }

                //-- R E C V
                case FFT_RECV:
                {
                    // io works
                    FFTSOCKET_ref_inc(fftsock);
                    FFTSOCKET_recv(fftsock,&byteio);                    
                    break;
                }
                case FFT_STOPIO:
                {
                  // Just consume complete state
                    break;
                }
                default:break;
            }
            FFTSOCKET_ref_dec(fftsock);  // dec ref counter and if it reasch 0 delete socket
        }
    }
    return 0;
}


// Stop session
int FFT_stop_session (FFTCONTEXT* fft,FFT_session* session)
{
    FFTSOCKET* sock = NULL;
    HANDLE* handles = NULL;

    if (fft != NULL && session != NULL)
    {
        ::EnterCriticalSection (&(fft->cs));

        for(int i = 0; i < session->socks.size(); i++)
        {
            sock = session->socks[i];           
            ::PostQueuedCompletionStatus(fft->hIOCP,0,FFT_STOPIO,&(sock->overlapped));
        }

        ::LeaveCriticalSection (&(fft->cs));
    }
    return 0;
}


int FFTSOCKET_ref_inc (FFTSOCKET* sock)
{
    return ::InterlockedIncrement(&(sock->ref));
}

int FFTSOCKET_ref_dec (FFTSOCKET* sock)
{
    int rst = 0;
    if(sock->ref == 0)
    {
        rst = 1;
    }
    else if(::InterlockedDecrement(&(sock->ref))==0)
    {   
        cout<<endl<<"sock delete:"<<sock->port<<flush;
        if(sock->wsabuf.buf) VirtualFree(sock->wsabuf.buf,0,MEM_RELEASE);
        sock->wsabuf.buf = NULL;
        sock->wsabuf.len = 0;
        WSACloseEvent(sock->overlapped.hEvent);

        if(sock->ai != NULL) freeaddrinfo(sock->ai);

        LINGER lingerStruct;
            lingerStruct.l_onoff  = 1;
                lingerStruct.l_linger = 0;
        ::setsockopt(sock->socket, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct));

        shutdown(sock->socket,SD_BOTH);
        closesocket(sock->socket);
        sock->socket = INVALID_SOCKET;

        delete sock;
        sock = NULL;

        rst = 2;        
    }
    return rst;
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Mark Yang
  • 226
  • 3
  • 16
  • You should be incrementing the reference count of the socket each time you submit an operation. Keep in mind that `closesocket` and `shutdown` will _not_ clear your items from the completion queue, it will just make them fail quicker. – Mark Nunberg Jul 12 '14 at 15:32
  • Also, can `FFT_stop_session()` be called twice? The proper way to handle this is to set a flag in the socket indicating whether it was closed or not - so that you don't accidentally submit the same event twice. – Mark Nunberg Jul 12 '14 at 15:36
  • Could you tell me more about using 'flag'..I posted FFT_STOPIO with PostQueue..to stop. – Mark Yang Jul 12 '14 at 16:03
  • If I make some flag in FFTSOCKET to indicate socket is close or not. At first close call..socket closed and all bundled variable maybe deleted(should be). and if I trying to access already deleted FFTSOCKET. Already there is no flag or datum...Could you give some advice how to make structure ? – Mark Yang Jul 12 '14 at 16:22
  • I mean simply something like: `if (sock->close_requested == 0) { PostQueuedCompletionStatus(...); sock->closed_requested = 1; }` – Mark Nunberg Jul 12 '14 at 16:58
  • Also keep in mind (and I don't know how your locks work) that the call to PostQueuedCompletionStatus will immediately unblock the IOCP polling theead – Mark Nunberg Jul 12 '14 at 17:02

0 Answers0