Worrying issue with Windows 8 and AcceptEx...

There’s an interesting question over on stack overflow about a perceived change in IOCP behaviour on Windows 8 (and Server 2012 RC).

The question includes some code which demonstrates how an overlapped AcceptEx() call is blocked on by the thread that issued it being blocked inside a call to ReadFile() at the time that the AcceptEx() completes. The completion for the AcceptEx() is delayed until the ReadFile() completes even though a thread is waiting for completions on the IOCP associated with the socket. The “delaying” behaviour only shows up on Windows 8 and Windows Server 2012 RC. On all other platforms everything works “as expected” and the fact that the thread that issued the AcceptEx() has blocked in no way affects the completion of the accept.

I can’t see anything wrong with the example code (and I’ve also tested with code which loads AcceptEx() “correctly” using WSAIoctl(), but I may be missing something… I can reproduce the issue here and I can confirm that the problem does not affect WSARecv() calls (that is, I changed the example to use WSAAccept() to accept the connection in a blocking manner and then issue an overlapped WSARecv() before entering the blocking ReadFile() and everything works as expected.

This is a slightly worrying change for those of us using AcceptEx() from arbitrary threads! I’ve yet to check to see if the stalled accept completion blocks the head of the IOCP and stalls ALL subsequent completions on the IOCP or if it is simply blocking the accept completion…

With The Server Framework you could switch to disabling JETBYTE_STREAM_SOCKETS_SKIP_MARSHAL_TO_IO_POOL and force all I/O to be done by one of the I/O threads. Assuming you perform no blocking calls on your I/O threads then you would be fine.

I expect I’ll add a further option which will let you forcibly marshal just AcceptEx requests to the I/O pool when running on Windows 8/Server 2012… Unfortunately existing code which uses AcceptEx and is compiled with JETBYTE_STREAM_SOCKETS_SKIP_MARSHAL_TO_IO_POOL enabled could fall foul of this rather strange change in the underlying operating system.

Hopefully this is a bug which will get fixed pretty quickly!