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;
}