触发EPOLLONESHOT事件后关闭Socket,是否需手动调用EPOLL_CTL_DEL?
EPOLLONESHOT触发后,关闭Socket前需要调用EPOLL_CTL_DEL吗?
答案是必须调用,原因如下:
事件禁用和从epoll实例移除是两码事
EPOLLONESHOT的作用只是让该Socket的事件触发一次后暂停通知,但Socket仍然和epoll实例保持关联,内核会维护对应的关联数据。而EPOLL_CTL_DEL是彻底将Socket从epoll的监控列表中移除,释放内核中对应的关联资源。避免资源泄漏
有些内核版本不会在Socket关闭时自动清理epoll中的关联条目,如果长期不调用EPOLL_CTL_DEL,会导致内核资源占用累积。不要依赖内核的“自动清理”行为,这并非标准规定,不同系统的实现存在差异。调用
EPOLL_CTL_DEL不会报错
只要Socket和epfd处于有效状态,即便事件已经被禁用,调用epoll_ctl(epfd, EPOLL_CTL_DEL, some_socket, NULL)也是安全的,不会返回错误。如果Socket已经关闭,调用可能会返回EBADF,但此时Socket本身已无效,不会造成资源泄漏,忽略该错误即可。
附上你的代码示例:
struct epoll_event ev, events[20]; ev.events = EPOLLOUT | EPOLLONESHOT; ev.data.sock = some_socket; epoll_ctl(epfd, EPOLL_CTL_ADD, some_socket, &ev); // then the EPOLLOUT event has triggered by epoll_wait epoll_ctl(epfd, EPOLL_CTL_DEL, some_socket, NULL); // should it be called? will it cause error?
内容的提问来源于stack exchange,提问作者benrush
相关产品推荐
相关产品推荐

