It also made me think that using wait_handle here makes things racy: if another thread waits on the async, gets it satisfied (which closes it), _after_ we've returned the handle to the cancelling thread, but _before_ the cancelling thread has started waiting on it, the cancelling thread will try to wait on an invalid handle.
I think you're right, we probably need a separate ad-hoc handle for cancellation.
I'm also not completely sure about putting all the cancelled asyncs in a process-wide list. Other threads cancelling async in the same process would wait on all the process previously cancelled asyncs, and maybe that would need to be done per-thread? Still, is it an issue if cancelled async are possibly short-lived?
I don't think this one is an issue? asyncs are flagged immediately for cancellation and are then ignored for future `NtCancelIoFile()` calls.
Then, there was a change in your code that cleared the async signaled flag before cancelling it, I'm not sure why it was needed and I removed it.
As I recall, I had to originally add it otherwise the `select` inside `NtCancelIoFile()` would be immediately satisfied i.e. it wouldn't wait for the actual async cancellation.