fish-shell/fish-shell · critical
eventfd
Error message
eventfd
What it means
FdMonitor::new creates its wakeup pipe via libc::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK) on platforms with eventfd support. If eventfd returns a negative fd (kernel too old, fd limit exhausted, or out of memory), fish prints perror("eventfd") and calls exit_without_destructors(1), aborting the process immediately.
Source
Thrown at src/fd_monitor.rs:49
/// [`try_consume()`](FdEventSignaller::try_consume) may be used to consume the event.
/// Importantly this is async signal safe. Of course it is `CLOEXEC` as well.
pub struct FdEventSignaller {
// Always the read end of the fd; maybe the write end as well.
fd: OwnedFd,
#[cfg(not(have_eventfd))]
write: OwnedFd,
}
impl FdEventSignaller {
/// The default constructor will abort on failure (fd exhaustion).
/// This should only be used during startup.
pub fn new() -> Self {
cfg_if! {
if #[cfg(have_eventfd)] {
// Note we do not want to use EFD_SEMAPHORE because we are binary (not counting) semaphore.
let fd = unsafe { libc::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK) };
if fd < 0 {
perror("eventfd");
exit_without_destructors(1);
}
use crate::fds::heightenize_fd;
let Ok(fd) = heightenize_fd(unsafe { OwnedFd::from_raw_fd(fd) }, true) else {
perror("eventfd");
exit_without_destructors(1);
};
Self {
fd
}
} else {
// Implementation using pipes.
let Ok(pipes) = make_autoclose_pipes() else {
exit_without_destructors(1);
};
make_fd_nonblocking(pipes.read.as_raw_fd()).unwrap();
make_fd_nonblocking(pipes.write.as_raw_fd()).unwrap();
Self {View on GitHub (pinned to edb719d76c)
Solutions
- Raise the file descriptor limit: `ulimit -n 65536` or adjust RLIMIT_NOFILE / systemd LimitNOFILE
- Check seccomp/container policy (Docker/Podman) allows the eventfd(2) syscall
- Confirm the kernel supports eventfd (CONFIG_EVENTFD=y); otherwise rebuild fish for a non-eventfd configuration
- Inspect `cat /proc/sys/fs/file-nr` for system-wide fd exhaustion
Defensive patterns
Strategy: retry
Validate before calling
# shell check before launching fish
if [ "$(cat /proc/sys/fs/file-nr | awk '{print $1}')" -gt "$(ulimit -n)" -o "$(ulimit -n)" -lt 1024 ]; then
echo "fd limit too low / nearly exhausted" >&2
fi Type guard
null
Try / catch
null
Prevention
- Raise RLIMIT_NOFILE in shell profile or systemd unit (LimitNOFILE)
- Allow eventfd(2) in container seccomp profiles
- Monitor /proc/sys/fs/file-nr for system-wide fd exhaustion
- Ensure kernel has CONFIG_EVENTFD enabled before deploying
When it happens
Trigger: Startup or first use of FdMonitor when the eventfd(2) syscall fails: RLIMIT_NOFILE exhausted (EMFILE), ENFILE/EINTR persisting, or running on a kernel/container without eventfd support despite the build flag have_eventfd being enabled.
Common situations: Containers/seccomp profiles blocking eventfd, hitting the file-descriptor limit after many open files/sockets, very old kernels or minimal embedded systems where CONFIG_EVENTFD is disabled.
AI-assisted analysis of fish-shell/fish-shell@edb719d76c (2026-09-03).
Data as JSON: /api/errors/0e965b88025b3466.
Report an issue: GitHub.