I am currently building something that uses epoll
. It works pretty nice, but it would be good to have a notification when a file descriptor gets removed from epoll
when the underlying fd
is closed.
Is there a way to get a notification from epoll
as soon as an fd
is closed?
No. Here's a Zig program to demonstrate:
const std = @import("std");
pub fn main() !void {
const epollfd = blk: {
const rc = std.os.linux.epoll_create1(std.os.linux.EPOLL_CLOEXEC);
const err = std.os.linux.getErrno(rc);
if (err != 0) return error.EpollCreateFailed;
break :blk @intCast(i32, rc);
};
defer std.os.close(epollfd);
var pipe: [2]i32 = undefined;
{
const rc = std.os.linux.pipe2(&pipe, std.os.linux.O_CLOEXEC);
const err = std.os.linux.getErrno(rc);
if (err != 0) return error.PipeCreateFailed;
}
var ev: std.os.linux.epoll_event = undefined;
ev.events = std.os.linux.EPOLLIN | std.os.linux.EPOLLET;
ev.data.fd = pipe[0];
{
const rc = std.os.linux.epoll_ctl(epollfd, std.os.linux.EPOLL_CTL_ADD, pipe[0], &ev);
const err = std.os.linux.getErrno(rc);
if (err != 0) return error.EpollCtlFailed;
}
const thread = try std.os.spawnThread(pipe[0], threadStart);
var events: [10]std.os.linux.epoll_event = undefined;
const nfds = blk: {
std.debug.warn("epoll wait\n");
const rc = std.os.linux.epoll_wait(epollfd, &events, @intCast(u32, events.len), -1);
std.debug.warn("epoll wakeup\n");
const err = std.os.linux.getErrno(rc);
if (err != 0) return error.EpollWaitFailed;
break :blk rc;
};
if (nfds != 1) return error.NotExactly1FileDescriptor;
std.debug.assert(events[0].data.fd == pipe[0]);
thread.wait();
}
fn threadStart(fd: i32) void {
std.os.time.sleep(1, 0);
std.debug.warn("close fd\n");
std.os.close(fd);
}
It outputs:
epoll wait
close fd
^C
(I had to kill it with Ctrl+C because it never woke up.)
Here's the strace output:
execve("./test", ["./test"], 0x7fff311ff208 /* 122 vars */) = 0
epoll_create1(EPOLL_CLOEXEC) = 3
pipe2([4, 5], O_CLOEXEC) = 0
epoll_ctl(3, EPOLL_CTL_ADD, 4, {EPOLLIN|EPOLLET, {u32=4, u64=4}}) = 0
mmap(NULL, 8388608, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0) = 0x7fd082ed9000
clone(child_stack=0x7fd0836d8fd8, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID|0x400000, parent_tidptr=0x7fd0836d8fe4, child_tidptr=0x7fd0836d8fe4) = 13547
strace: Process 13547 attached
[pid 13546] write(2, "epoll wait\n", 11epoll wait
<unfinished ...>
[pid 13547] nanosleep({tv_sec=1, tv_nsec=0}, <unfinished ...>
[pid 13546] <... write resumed> ) = 11
[pid 13546] epoll_wait(3, <unfinished ...>
[pid 13547] <... nanosleep resumed> 0x7fd0836d8f20) = 0
[pid 13547] write(2, "close fd\n", 9close fd
) = 9
[pid 13547] close(4) = 0
[pid 13547] exit(0) = ?
[pid 13547] +++ exited with 0 +++
^Cstrace: Process 13546 detached
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With