On Thu, 19 Jul 2012 08:25:51 +0700 Benny Prijono <bennylp at teluu.com> wrote: > On Wed, Jul 18, 2012 at 6:49 PM, Timo Teras <timo.teras at iki.fi> wrote: > > > Hi, > > > > This is slightly disappointing. IOCP is way better on Windows than > > the select() based things. And as I noted before the select() > > thingy is quite broken too. > > > > I would really prefer the simple race condition to be fixed, and > > IOCP to be enabled by default on windows. > > > > > I would prefer that too. But if you read the ticket, it's pretty > difficult to solve, or at least for me, since the problem is not on > us. If it's simple for you then by all means share a patch. :) It seems that there has been a misunderstanding how the Windows async IO works. The OVERLAPPED structure is owned by windows API until the corresponding notification is sent by the API. That is, even when the request gets cancelled - you will always get the notification that it was cancelled. Your code must not use or free the OVERLAPPED structure *or* the data buffer it refers to until the matching reply is received. That is even CancelIo is asynchronous; and when doing CloseHandle, CancelIoEx is implied. Thus you should not reuse OVERLAPPED structures until it has been acked by windows. Reference reading: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363789%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/aa365683%28v=vs.85%29.aspx http://www.osronline.com/showthread.cfm?link=213975 As short summary: 1. CloseHandle will synchronously post the IO cancellations. 2. OVERLAPPED updates are done asynchronously in usermode APCs so it is not guaranteed that all these are updated when CloseHandle returns. 3. Thus you must not touch/free OVERLAPPED structures or the buffers they refer to until you get the completion message handled for them. On older Windowses it may have *seemed* that the notification is handled before CloseHandle returns. But that has been only because of luck in how scheduler has decided to execute your threads. Solutions that come up to my mind: - if the pool is deleted, the destructor should wait synchronously that each cancel notification is received before continuing - or async version: increase pool refcount everytime async operation is posted, and decrease it when an iocp notification is received - the OVERLAPPED structures *and* databuffers could be kept on separate pool managed by ioqueue, so the memory will not get freed too early. -Timo