Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix kernel close and select bug #89

Merged
merged 7 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/safeposix/syscalls/fs_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1881,8 +1881,8 @@ impl Cage {
}
}

pub fn kernel_close(_fdentry: fdtables::FDTableEntry, kernelfd: u64) {
pub fn kernel_close(fdentry: fdtables::FDTableEntry, _count: u64) {
let _ret = unsafe {
libc::close(kernelfd as i32)
libc::close(fdentry.underfd as i32)
};
}
75 changes: 39 additions & 36 deletions src/safeposix/syscalls/net_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,19 +482,12 @@ impl Cage {
}

/*
* fd_set is used in the Linux select system call to specify the file descriptor
* to be monitored. fd_set is actually a bit array, each bit of which represents
* a file descriptor. fd_set is a specific data type used by the kernel, so we need
* to make sure the final variable we pass to the kernel is in the format that the
* kernel expects. That's why we choose to use FD_SET function instead of doing
* bitmask by ourself. We use Vec to express the fd_set of the virtual file descriptor
* in Lind, and expand the conversion function between lind fd_set and kernel fd_set.
* The design logic for select is first to categorize the file descriptors (fds) received from the user based on FDKIND.
* Specifically, kernel fds are passed to the underlying libc select, while impipe and imsock fds would be processed by the
* in-memory system. Afterward, the results are combined and consolidated accordingly.
*
* We chose to use bit-set to implement our own fd_set data structure because bit-set
* provides efficient set operations, allowing us to effectively represent and manipulate
* file descriptor sets. These operations can maximize the fidelity to the POSIX fd_set
* characteristics.
* Reference: https://docs.rs/bit-set/latest/bit_set/struct.BitSet.html
* (Note: Currently, only kernel fds are supported. The implementation for in-memory pipes is commented out and will require
* further integration and testing once in-memory pipe support is added.)
*
* select() will return:
* - the total number of bits that are set in readfds, writefds, errorfds
Expand All @@ -509,7 +502,6 @@ impl Cage {
mut errorfds: Option<&mut fd_set>,
rposix_timeout: Option<RustDuration>,
) -> i32 {

let mut timeout;
if rposix_timeout.is_none() {
timeout = libc::timeval {
Expand All @@ -532,25 +524,36 @@ impl Cage {
fdkindset.insert(FDKIND_KERNEL);

let (selectbittables, unparsedtables, mappingtable) = fdtables::prepare_bitmasks_for_select(self.cageid, nfds as u64, orfds.copied(), owfds.copied(), oefds.copied(), &fdkindset).unwrap();

// libc select()
let (readnfd, mut real_readfds) = selectbittables[0].get(&FDKIND_KERNEL).unwrap();
let (writenfd, mut real_writefds) = selectbittables[1].get(&FDKIND_KERNEL).unwrap();
let (errornfd, mut real_errorfds) = selectbittables[2].get(&FDKIND_KERNEL).unwrap();
// Check:
// 1. If there exists virtual fd_set values
// 2. If there exists kernel fd_set
// If yes -- Convert into kernel fd_set structure
// If no -- Set it to null
let (readnfd, mut real_readfds) = selectbittables
.get(0)
.and_then(|table| table.get(&FDKIND_KERNEL).cloned())
.unwrap_or((0, fdtables::_init_fd_set()));
let (writenfd, mut real_writefds) = selectbittables
.get(1)
.and_then(|table| table.get(&FDKIND_KERNEL).cloned())
.unwrap_or((0, fdtables::_init_fd_set()));
let (errornfd, mut real_errorfds) = selectbittables
.get(2)
.and_then(|table| table.get(&FDKIND_KERNEL).cloned())
.unwrap_or((0, fdtables::_init_fd_set()));

let mut realnewnfds = readnfd;
if realnewnfds < writenfd {
realnewnfds = writenfd;
} else if realnewnfds < errornfd {
realnewnfds = errornfd;
}
let mut realnewnfds = readnfd.max(writenfd).max(errornfd);


// Ensured that null_mut is used if the Option is None for fd_set parameters.
let ret = unsafe {
libc::select(
*realnewnfds as i32,
&mut real_readfds as *mut fd_set,
&mut real_writefds as *mut fd_set,
&mut real_errorfds as *mut fd_set,
realnewnfds as i32,
&mut real_readfds as *mut _,
&mut real_writefds as *mut _,
&mut real_errorfds as *mut _,
&mut timeout as *mut timeval)
};

Expand All @@ -560,14 +563,14 @@ impl Cage {
}

// impipe/imsock select()
let start_time = starttimer();
// let start_time = starttimer();

let end_time = match rposix_timeout {
Some(time) => time,
None => RustDuration::MAX,
};
// let end_time = match rposix_timeout {
// Some(time) => time,
// None => RustDuration::MAX,
// };

let mut return_code = 0;
// let mut return_code = 0;
let mut unreal_read = HashSet::new();
let mut unreal_write = HashSet::new();

Expand Down Expand Up @@ -622,7 +625,7 @@ impl Cage {
// Revert result
let (read_flags, read_result) = fdtables::get_one_virtual_bitmask_from_select_result(
FDKIND_KERNEL,
nfds as u64,
realnewnfds as u64,
Some(real_readfds),
unreal_read,
None,
Expand All @@ -635,7 +638,7 @@ impl Cage {

let (write_flags, write_result) = fdtables::get_one_virtual_bitmask_from_select_result(
FDKIND_KERNEL,
nfds as u64,
realnewnfds as u64,
Some(real_writefds),
unreal_write,
None,
Expand All @@ -648,7 +651,7 @@ impl Cage {

let (error_flags, error_result) = fdtables::get_one_virtual_bitmask_from_select_result(
FDKIND_KERNEL,
nfds as u64,
realnewnfds as u64,
Some(real_errorfds),
HashSet::new(), // Assuming there are no unreal errorsets
None,
Expand All @@ -658,7 +661,7 @@ impl Cage {
if let Some(errorfds) = errorfds.as_mut() {
**errorfds = error_result.unwrap();
}

// The total number of descriptors ready
(read_flags + write_flags + error_flags) as i32
}
Expand Down
Loading