首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IOCP循环终止可能导致内存泄漏?如何优雅地关闭IOCP环路

IOCP循环终止可能导致内存泄漏?如何优雅地关闭IOCP环路
EN

Stack Overflow用户
提问于 2013-03-21 20:36:49
回答 2查看 1.3K关注 0票数 3

我有一个经典的IOCP回调函数,它将i/o挂起的请求出队,处理它们,然后释放它们,方法如下:

代码语言:javascript
复制
struct MyIoRequest { OVERLAPPED o; /* ... other params ... */ };
bool is_iocp_active = true;

DWORD WINAPI WorkerProc(LPVOID lpParam)
{
    ULONG_PTR dwKey;
    DWORD dwTrans;
    LPOVERLAPPED io_req;
    while(is_iocp_active)
    {
        GetQueuedCompletionStatus((HANDLE)lpParam, &dwTrans, &dwKey, (LPOVERLAPPED*)&io_req, WSA_INFINITE); 
       // NOTE, i could use GetQueuedCompletionStatusEx() here ^ and set it in the 
       // alertable state TRUE, so i can wake up the thread with an ACP request from another thread!

        printf("dequeued an i/o request\n");
        // [ process i/o request ]
        ...

        // [ destroy request ]
        destroy_request(io_req);
    }
    // [ clean up some stuff ] 
    return 0;
}

然后,在代码中,我将在某个地方:

代码语言:javascript
复制
MyIoRequest * io_req = allocate_request(...params...);
ReadFile(..., (OVERLAPPED*)io_req);

这就是完美的工作。

现在我的问题是:如果我想立即关闭IOCP队列而不导致泄漏,该怎么办?(例如,应用程序必须退出)我的意思是:如果我将is_iocp_active设置为'false',那么下次GetQueuedCompletionStatus()将新的i/o请求出队时,这将是最后一个i/o请求:它将返回,导致线程退出,并且当一个线程退出时,系统将简单地取消所有挂起的i/o请求。

但我在调用ReadFile()时实例化的'MyIoRequest‘类型的结构根本不会被销毁:系统已经取消了挂起的i/o请求,但我必须手动销毁我创建的那些结构,否则当我停止循环时,我将泄漏所有挂起的i/o请求!

那么,我该怎么做呢?仅仅将该变量设置为false来停止IOCP循环是错误的吗?请注意,即使我使用APC请求来停止可警报线程,也会发生这种情况。

我想到的解决方案是将每个“MyIoRequest”结构添加到一个队列/列表中,然后在GetQueuedCompletionStatusEx返回时将它们出队,但这不应该造成一些瓶颈吗,因为这样的MyIoRequest结构的入队/出队过程必须是互锁的?也许我误解了如何使用IOCP循环。有人能给这个话题带来一些启发吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-03-22 16:37:07

我通常关闭IOCP线程的方式是发布我自己的“请立即关闭”的完成。这样,您就可以干净利落地关闭并处理所有挂起的完成,然后关闭线程。

这样做的方法是调用PostQueuedCompletionStatus(),其中0表示字节数、完成键和pOverlapped。这意味着完成键是唯一的值(你不会有一个有效的文件或套接字有一个零句柄/完成键)。

第一步是关闭完成的源代码,因此关闭或中止你的套接字连接,关闭文件等。一旦所有这些都关闭了,你就不能再生成任何完成包,所以你可以发布你的特殊“0”完成;为你的IOCP服务的每个线程发布一个完成包。一旦线程获得了一个'0‘完成键,它就会退出。

票数 4
EN

Stack Overflow用户

发布于 2013-03-21 20:55:46

如果您要终止应用程序,并且没有压倒一切的理由不这样做,(例如。关闭数据库连接,进程间共享内存问题),调用ExitProcess(0)。

否则,为所有套接字句柄调用CancelIO(),并在所有取消的完成传入时处理它们。

先试试ExitProcess()吧!

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15547741

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档