diff --git a/src/platform/redox/epoll.rs b/src/platform/redox/epoll.rs index b9dd7597ea..4cfb41df35 100644 --- a/src/platform/redox/epoll.rs +++ b/src/platform/redox/epoll.rs @@ -64,36 +64,7 @@ impl PalEpoll for Sys { // systems. If this is needed, use a box or something data: unsafe { (*event).data.u64 as usize }, }; - // Registering an fd with /scheme/event can transiently fail - // 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), - } - } + Sys::write(epfd, &ev)?; } EPOLL_CTL_DEL => { Sys::write( diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 5dcc4136d9..e3ced16b88 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -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 (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<()> {