小心使用IOCP完成端口

s = createsocket();    //假定s返回值是10

CreateIoCompletionPort(s, m_hCompletionPort, (DWORD_PTR)&A, 0);

WSASend(s,...);

WSASend(s,...);

WSASend(s,...);

WSASend(s,...);

WSASend(s,...);

这个时候,完成端口里累计了多条跟s相关的数据,由于完成端口的线程暂时繁忙,未来得及处理s关闭后的失败数据

closesocket(s);

s = createsocket();    //s的值仍然是10

CreateIoCompletionPort(s, m_hCompletionPort, (DWORD_PTR)&B, 0);

好了,本线程到此告一个段落,回到完成端口线程上来:

GetQueuedCompletionStatus(m_hCompletionPort,&dwTransferred,(LPDWORD)&pCustomData,(OVERLAPPED *) ...,INFINITE);

问:

pCustomData是指向A还是指向B?

 

在我的设计意识里,pCustomData应该指向A,且我没有再任何文档和论坛里看到提及此问题,且无论是官方的还是非官方的例子都是我这样的用法。

实际上,pCustomData指向了B

 

此时,WSASend(和其他函数)操作的数据和在GetQueuedCompletionStatus后处理的数据不再绑定到一致的数据上,bug由此产生,且无法直接观察,非常难重现,因为closesocket后也不是立即调用createsocket,且socket句柄被立即复用的概率实在不大,因为不是立即复用,完成端口线程就把老句柄相关的数据处理完毕了。

 

这个问题困扰<乱武>项目组和测试组人员至少三周,终在昨日(2008-8.31)获知原因并得到解决。老谢说值得庆贺,该出去搓一顿。吾深表赞同,不过就是要我买单有些许遗憾——因为代码是我写的。

你可能感兴趣的:(小心使用IOCP完成端口)