fix(redox): translate POSIX F_DUPFD_CLOEXEC (1030) to Redox syscall ABI (5)
fcntl(F_DUPFD_CLOEXEC) reached redox_rt/kernel with the POSIX/C value 1030 instead of the Redox syscall value (syscall::F_DUPFD_CLOEXEC=5). redox_rt did not recognize it as a dup, forwarded the raw command to the kernel, and the kernel's fcntl fell through to its EINVAL catch-all. That made OwnedFd::try_clone() return EINVAL, which broke tokio Runtime::build() (its I/O reactor try_clones the epoll fd) for every tokio user on Redox: all the zbus system daemons (sessiond/polkit/udisks/upower) and the login shell. F_DUPFD and plain dup worked because they share the same value in both namespaces; F_DUPFD_CLOEXEC was the sole untranslated command. Also drop the ineffective epoll_ctl EINVAL/EBADF retry loop: it was based on a disproven 'transient scheme churn' theory; epoll registrations always succeed immediately. The real dup failure is fixed above.
This commit is contained in:
@@ -64,36 +64,7 @@ impl PalEpoll for Sys {
|
|||||||
// systems. If this is needed, use a box or something
|
// systems. If this is needed, use a box or something
|
||||||
data: unsafe { (*event).data.u64 as usize },
|
data: unsafe { (*event).data.u64 as usize },
|
||||||
};
|
};
|
||||||
// Registering an fd with /scheme/event can transiently fail
|
Sys::write(epfd, &ev)?;
|
||||||
// with EINVAL/EBADF while the scheme backing `fd` is still
|
|
||||||
// starting up or the fd-table is churning during early boot
|
|
||||||
// (e.g. a tokio/mio reactor built by a daemon that races ahead
|
|
||||||
// of ipcd's uds_stream scheme). Without recovery, tokio's
|
|
||||||
// Runtime::build aborts the whole runtime, killing every
|
|
||||||
// zbus-based daemon and any tokio program (including the login
|
|
||||||
// shell). Retry with a short backoff so the registration
|
|
||||||
// succeeds once the scheme settles; a genuinely permanent
|
|
||||||
// failure still surfaces after the bounded window. This mirrors
|
|
||||||
// the park-path recovery in the P0-epoll-redox-recovery tokio
|
|
||||||
// patch, but at the registration site the patch cannot reach.
|
|
||||||
let mut attempts: u32 = 0;
|
|
||||||
loop {
|
|
||||||
match Sys::write(epfd, &ev) {
|
|
||||||
Ok(_) => break,
|
|
||||||
Err(Errno(err))
|
|
||||||
if (err == EINVAL || err == EBADF) && attempts < 400 =>
|
|
||||||
{
|
|
||||||
attempts += 1;
|
|
||||||
let req = syscall::data::TimeSpec {
|
|
||||||
tv_sec: 0,
|
|
||||||
tv_nsec: 5_000_000, // 5ms; up to ~2s total
|
|
||||||
};
|
|
||||||
let mut rem = syscall::data::TimeSpec::default();
|
|
||||||
let _ = syscall::nanosleep(&req, &mut rem);
|
|
||||||
}
|
|
||||||
Err(err) => return Err(err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EPOLL_CTL_DEL => {
|
EPOLL_CTL_DEL => {
|
||||||
Sys::write(
|
Sys::write(
|
||||||
|
|||||||
@@ -477,7 +477,24 @@ impl Pal for Sys {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(redox_rt::sys::fcntl(fd as usize, cmd as usize, args as usize)? as c_int)
|
// The POSIX/C value of `F_DUPFD_CLOEXEC` exposed by <fcntl.h> (1030,
|
||||||
|
// matching Linux so that libc/std/mio hardcode it) does NOT match the
|
||||||
|
// Redox syscall-ABI value that redox_rt and the kernel understand
|
||||||
|
// (`syscall::F_DUPFD_CLOEXEC`, 5). Every other fcntl command that reaches
|
||||||
|
// redox_rt shares the same numeric value in both namespaces, so
|
||||||
|
// F_DUPFD_CLOEXEC is the single command that must be translated here.
|
||||||
|
// Without this, redox_rt does not recognize 1030 as a dup, forwards the
|
||||||
|
// raw command to the kernel, and the kernel's fcntl falls through to its
|
||||||
|
// catch-all EINVAL arm. That made `OwnedFd::try_clone()` fail with
|
||||||
|
// EINVAL, which in turn broke `tokio::runtime::Builder::build()` (its I/O
|
||||||
|
// reactor try_clones the epoll fd) for every tokio user on Redox — all
|
||||||
|
// the zbus system daemons and the login shell.
|
||||||
|
let redox_cmd = if cmd == fcntl::F_DUPFD_CLOEXEC {
|
||||||
|
syscall::F_DUPFD_CLOEXEC
|
||||||
|
} else {
|
||||||
|
cmd as usize
|
||||||
|
};
|
||||||
|
Ok(redox_rt::sys::fcntl(fd as usize, redox_cmd, args as usize)? as c_int)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fdatasync(fd: c_int) -> Result<()> {
|
fn fdatasync(fd: c_int) -> Result<()> {
|
||||||
|
|||||||
Reference in New Issue
Block a user