2008-05-11

IOCP 的资源释放问题

关键字: iocp
在参考了一些资料,并且尝试了几次之后,也逐渐想到了一个用来安全释放 IOCP 资源的办法。
http://groups.google.com/group/dev4server/browse_thread/thread/29a91064931a628e

接着发现有人已经把这种方案描述的很清楚了
http://blog.codingnow.com/2007/07/robust.html#comment-12142

对大家的讨论不置可否,但是使用ID代替指针确实在某些方面是有益处的。
而某些时候我们无法使用智能指针。举个例子,完成端口中

GetQueuedCompletionStatus(
*pTHIS,
&dwNumberBytes,
(PULONG_PTR)&lpKey,
&lpEvent,
INFINITE
);


其中的lpKey是一个非常关键的变量,我们一般把它置为一个对象的指针。这样我们就可以通过这个指针去访问该对象。

但是事实上很多时候这个指针的生命周期是不固定的,而由于其传入的是PULONG_PTR类型的值,我们又不能直接使用智能指针。要么就要繁琐的执行addref 和 release 这样的操作而完全丢失智能指针的优越性。

可是,如果这里传入的是一个ID或者HANDLE,为其对象的访问增加一层间接性。那么我们就可以预防非法的指针访问,从而达到安全的生命周期管理。
评论
iunknown 2008-05-12
之前一直困扰在如何等待所有这些异步 IO 操作完成(包括被取消),现在想到了一个办法。
IOCP 的内部实现是遵循 FIFO 的,在 closesocket 之后,不要立即 free ,而是重新
PostQueuedCompletionStatus 一个完成特殊事件给 GQCS ,通过 GQCS 得到这个事件,接着在进行 free 。

这样就相当于变相地等待所有这些异步 IO 完成了。
因为 closesocket 之后,所有 IO 都会被取消,这些取消的操作将在 GQCS 的队列中等待被处理,
而用 PostQueuedCompletionStatus 投递的特殊事件,应该排在这些被取消的操作之后。
iunknown 2008-05-11
使用 BoundsChecker 进行了检查,报了下面的这种错误。
从描述来看,应该是某段内存被释放之后,接着这段内存继续被程序进行了修改。

引用

OutDbStr: HEAP[testiocpecho.exe]:
OutDbStr: HEAP: Free Heap block 123c1a0 modified at 123c1d4 after it was freed
OutDbStr: HEAP[testiocpecho.exe]:
OutDbStr: HEAP: Free Heap block 1680040 modified at 1680074 after it was freed
OutDbStr: Heap corruption detected at 0123C1A8
OutDbStr: HEAP[testiocpecho.exe]:
OutDbStr: HEAP: Free Heap block 123c1a0 modified at 123c1d4 after it was freed


http://msdn.microsoft.com/en-us/library/ms737582(VS.85).aspx

引用

An application should not assume that any outstanding I/O operations on a socket will all be guaranteed to completed when closesocket returns. The closesocket function will initiate cancellation on the outstanding I/O operations, but that does not mean that an application will receive I/O completion for these I/O operations by the time the closesocket function returns. Thus, an application should not cleanup any resources (WSAOVERLAPPED structures, for example) referenced by the outstanding I/O requests until the I/O requests are indeed completed.



从上面这段描述来看, IOCP 在内部是这样处理的:
在 WSASend 和 WSARecv 发出一个异步请求之后,如果一直都没有完成,直到 closesocket 引发这些操作被取消,在取消的过程中,IOCP 会对 OVERLAPPED 进行一些写操作。但是 IOCP 又没有提供一种等待这些操作完成的机制。那应该如何来处理这种情况呢?

一种可能的办法是在 closesocket 之后,不要立即释放 OVERLAPPED ,重新 POST 一个 CompletionStats 到 CompletionPort ,通过 GQCS 再次得到这个 OVERLAPPED ,然后释放?期望 GQCS 内部是 FIFO 的?被取消的 IO 操作,比重新 POST 的 CompletionStats 更早发生,因此会被先处理?
发表评论

您还没有登录,请登录后发表评论

iunknown
搜索本博客
我的相册
562c81ee-a4d4-351b-aa82-57a3972c22c6-thumb
vim
共 2 张
最近加入圈子
存档
最新评论