diff --git a/init/src/service.rs b/init/src/service.rs index 950e8d7ea4..716711dde2 100644 --- a/init/src/service.rs +++ b/init/src/service.rs @@ -38,8 +38,15 @@ pub enum ServiceType { fn create_pipe() -> io::Result<(File, OwnedFd)> { let mut fds = [0i32; 2]; - let res = unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) }; - if res != 0 { + // Use libc::pipe2() which goes through relibc's FILETABLE-managed path + // (FdGuard::open → SYS_OPENAT_INTO), keeping the userspace file table in + // sync with the kernel's file table. Using raw syscall::openat() + // (SYS_OPENAT) here would bypass the FILETABLE and create phantom fds + // that later cause EEXIST collisions when relibc's own pipe2() (called + // during Command::spawn fork+exec) tries to insert at a position the + // FILETABLE incorrectly thinks is free. + let ret = unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) }; + if ret != 0 { return Err(io::Error::last_os_error()); } let rd = unsafe { File::from_raw_fd(fds[0]) };