Windows程序在实现线程池时要注意Overlapped IO是否完成

windows有个限制,异步IO操作是绑定在发起IO请求的线程上的。一旦发起者线程退出,那么这个IO操作也就会被取消,而且没有callback会被调用。

MSDN中的WSASend函数的文档中有这么一段话:
"All I/O initiated by a given thread is canceled when that thread exits. For overlapped sockets, pending asynchronous operations can fail if the thread is closed before the operations complete. "

所以在调用WSASend方法时,务必要清楚自己在什么样的线程里。假如是在一个线程池中,并且这个线程池的线程数是可以动态增减的,那么就要小心了。万一你刚Send完,这个线程就exit了,那么就惨惨惨了!这种bug非常非常难以debug出来。

解决办法:
方案1.  ThreadPool的实现者通过GetThreadIOPendingFlag函数来得知是否可以安全退出
方案2.  所有的异步IO操作都先放到一个queue里,然后由特定的线程来处理这个queue

我刚发信问过了windows kernel team负责threadpool的人,他回答说windows自带的thread pool api考虑到了这一点,他在信中说:“Threadpool will not release threads while they have pending IRPs in them。This means your IO will complete even if it completes after you return the thread back to the Threadpool.” 同样的,.net 程序也是如此。

但是,我所见过的所有使用IOCP的程序,几乎全部都是自己制作的thread pool,没有使用操作系统的thread pool API。这些thread pool能实现干干净净shutdown的寥寥无几。




此博客中的热门博文

在windows下使用llvm+clang

少写代码,多读别人写的代码

tensorflow distributed runtime初窥