fix(redox-rt): close O_CLOEXEC fds individually in fexec_impl

The kernel proc scheme returns EBADF for writes to Filetable/NewFiletable
handles, so the bulk FileTableVerb::Close call was silently failing. Close
each O_CLOEXEC fd with SYS_CLOSE instead, which updates both the kernel file
table and the userspace FILETABLE. This unblocks Command::spawn() parents
waiting on the CLOEXEC sync pipe.
This commit is contained in:
Red Bear OS
2026-07-14 12:40:45 +09:00
parent aeabac730b
commit 7dee54808a
+15 -20
View File
@@ -493,11 +493,24 @@ pub fn fexec_impl(
let _siglock = crate::signal::tmp_disable_signals();
let fds_to_close = {
let guard = crate::current_filetable();
let old_filetable_fd = guard.fd().as_ref().map(|f| f.as_raw_fd());
let mut fds = alloc::vec::Vec::new();
for (fd, flags) in guard.iter() {
if fd == addrspace_selection_fd.as_raw_fd() {
continue; // Will be closed below
}
if Some(fd) == old_filetable_fd {
continue;
}
if fd == thread_fd.as_raw_fd() {
continue;
}
if fd == proc_fd.as_raw_fd() {
continue;
}
if fd == grants_fd.as_raw_fd() {
continue;
}
if flags & O_CLOEXEC == O_CLOEXEC || fd == image_file.as_raw_fd() {
fds.push(fd);
@@ -507,26 +520,8 @@ pub fn fexec_impl(
fds
};
let fds_to_close_bytes: &[u8] = unsafe {
core::slice::from_raw_parts(
fds_to_close.as_ptr() as *mut u8,
fds_to_close.len() * core::mem::size_of::<usize>(),
)
};
{
let filetable_fd = thread_fd.dup_into_upper(b"filetable-binary")?;
let _ = filetable_fd.call_wo(
fds_to_close_bytes,
CallFlags::empty(),
&[syscall::FileTableVerb::Close as u64],
);
}
{
let mut guard = crate::current_filetable();
for fd in fds_to_close {
let _ = guard.remove(fd);
}
for &fd in &fds_to_close {
let _ = crate::sys::close_raw(fd);
}
unsafe {