Sign in to follow this  
Kitt3n

iocp shutdown

Recommended Posts

Hello everyone, I've got a small iocp demo running. Using that I have a clientInterface and a serverInterface. The client logs in to the server (sends a 'login' packet) and the server 'parses' it and determines if the login is valid. The entire transmission part is working fine. Now the problem lies when the server gets a login and can't verify the credentials, and thus wants to disconnect the client. At that point I would just like to do a closesocket() to kick the client. This should (obviously) have no effect for already connected clients, and future clients trying to connect. Anyway, just after doing the closesocket(), I get a crash in one of the iocp-threads because it's accessing the TCPSocketIocp class I just deleted (the this-pointer in the associateDevice-call). So I'm looking for an 'unassociateDevice' which I can call (which doesn't exist apparently)... I considered a mutex - but the iocp-threads would start blocking each other, which is not really what I want. Any ideas on how to handle this?

class server
  manages a vector of <TCPSocketIocp> clients; // [index=clientid]

// Throw out specified client (eg because invalid login)
bool Server::doDisconnect (clientid)
{
  delete clients[clientid];
  clients[clientid]=0;
}

// Set  initial socket options
void TCPSocketIocp::initSocketOptions()
{
  // <lots of boring stuff here>

  // and finally we associate this sockets with the iocp
  g_iocp.associateDevice ((HANDLE) socket, (ULONG_PTR)this);
  // this call does sth like 
  // if (m_iocp != ::CreateIoCompletionPort(hDevice, m_iocp, completionKey, 
0))
}

TCPSocketIocp::~TCPSocketIocp()
{
  // disconnect
  if ( socket != INVALID_SOCKET )
  {
    // and now shutdown the socket
    closesocket( socket );
    socket = INVALID_SOCKET;
  }
}


Share this post


Link to post
Share on other sites
One more thing... In the TCPSocketIocp-destructor I can determine
if there are 'outstanding' iocp request running (since this class
manages handing out/receiving back of OVERLAPPED structures).

So my idea was to stop handing out new requests - and wait until
all pending requests are handled (ie we got the overlapped structures
back)...

The nasty thing is I can't just call a 'delete' on the TCPSocketIocp
class, but rather have to call an additional function waitForShutdown()
before I can delete..

However strangely enough the problem still remains... After the
waitForShutdown-function is called (and it's still looping/waiting),
I get a crash in the thread running the iocp code.



TCPSocketIocp::~TCPSocketIocp()
{
// disconnect
if ( socket != INVALID_SOCKET )
{
assert (contexts.size()==freeContexts.size() && "TCPSocketIocp::~TCPSocketIocp() outstanding io/requests!");
// and now close the socket
closesocket( socket );
socket = INVALID_SOCKET;
}
}

void TCPSocketIocp::waitForShutdown (void)
{
// Notify iocp to not process packets from this socket anymore
//g_iocp.postStatus ((ULONG_PTR)NULL, 0, NULL);
// shutdown socket (ie disable/ignore read & write operations on it)
::shutdown (socket, SD_BOTH);
// we have to wait until all outstanding contexts are released
while (contexts.size()!=freeContexts.size())
Sleep (5);
}


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this