Skip to content

Commit

Permalink
Bump to nix 0.28
Browse files Browse the repository at this point in the history
  • Loading branch information
slhmy committed Mar 16, 2024
1 parent 681144c commit 3c512b5
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 24 deletions.
2 changes: 1 addition & 1 deletion judge-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ description = "A judge library for online judge system"
[dependencies]
libc = "0.2"
libseccomp = "0.3"
nix = { version = "0.27", features = ["event", "fs", "process", "resource"] }
nix = { version = "0.28", features = ["event", "fs", "process", "resource"] }
log = "0.4"
anyhow = "1.0"
serde = "1"
Expand Down
51 changes: 31 additions & 20 deletions judge-core/src/judge/interact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::utils::get_pathbuf_str;

use nix::errno::Errno;
use nix::fcntl::{fcntl, FcntlArg, OFlag};
use nix::sys::epoll::{Epoll, EpollCreateFlags, EpollEvent, EpollFlags};
use nix::sys::epoll::{Epoll, EpollCreateFlags, EpollEvent, EpollFlags, EpollTimeout};
use nix::unistd::{pipe, read, write};
use std::fs::File;
use std::os::fd::BorrowedFd;
Expand All @@ -31,15 +31,18 @@ fn set_fd_non_blocking(fd: RawFd) -> Result<libc::c_int, JudgeCoreError> {
/// write the content of `from` to `to`, record to output.
/// `from` will be set to non-blocking mode.
fn pump_proxy_pipe(from: RawFd, to: RawFd, output: RawFd) -> Result<(), JudgeCoreError> {
log::debug!("Pumping from {} to {} with output {}", from, to, output);
set_fd_non_blocking(from)?;

let mut buf = [0; 1024];
loop {
match read(from, &mut buf) {
Ok(nread) => {
log::debug!("{} read. {} -> {}", nread, from, to);
write(to, &buf[..nread])?;
write(output, &buf[..nread])?;
// We should be really careful here
// not using OwnedFd here because it will close the fd
write(unsafe { BorrowedFd::borrow_raw(to) }, &buf[..nread])?;
write(unsafe { BorrowedFd::borrow_raw(output) }, &buf[..nread])?;
}
Err(e) => {
if e == Errno::EAGAIN || e == Errno::EWOULDBLOCK {
Expand Down Expand Up @@ -104,19 +107,19 @@ pub fn run_interact(
let (interactor_read_proxy, proxy_write_interactor) = pipe()?;

log::debug!("Adding read proxy fds to epoll");
add_epoll_fd(&epoll, proxy_read_user)?;
add_epoll_fd(&epoll, proxy_read_interactor)?;
add_epoll_fd(&epoll, proxy_read_user.as_raw_fd())?;
add_epoll_fd(&epoll, proxy_read_interactor.as_raw_fd())?;

log::debug!("Creating exit report pipes with epoll");
let (user_exit_read, user_exit_write) = pipe()?;
let (interactor_exit_read, interactor_exit_write) = pipe()?;
add_epoll_fd(&epoll, user_exit_read)?;
add_epoll_fd(&epoll, interactor_exit_read)?;
add_epoll_fd(&epoll, user_exit_read.as_raw_fd())?;
add_epoll_fd(&epoll, interactor_exit_read.as_raw_fd())?;

let mut user_listener = ProcessListener::new()?;
let mut interact_listener = ProcessListener::new()?;
user_listener.setup_exit_report(user_exit_write, USER_EXIT_SIGNAL);
interact_listener.setup_exit_report(interactor_exit_write, INTERACTOR_EXIT_SIGNAL);
user_listener.setup_exit_report(user_exit_write.as_raw_fd(), USER_EXIT_SIGNAL);
interact_listener.setup_exit_report(interactor_exit_write.as_raw_fd(), INTERACTOR_EXIT_SIGNAL);

if !PathBuf::from(&output_path).exists() {
File::create(output_path)?;
Expand All @@ -130,8 +133,8 @@ pub fn run_interact(
let mut user_sandbox = Sandbox::new(
config.program.executor.clone(),
config.runtime.rlimit_configs.clone(),
Some(user_read_proxy),
Some(user_write_proxy),
Some(user_read_proxy.as_raw_fd()),
Some(user_write_proxy.as_raw_fd()),
true,
)?;
user_listener.spawn_with_sandbox(&mut user_sandbox)?;
Expand All @@ -147,8 +150,8 @@ pub fn run_interact(
let mut interact_sandbox = Sandbox::new(
interactor_executor,
SCRIPT_LIMIT_CONFIG.clone(),
Some(interactor_read_proxy),
Some(interactor_write_proxy),
Some(interactor_read_proxy.as_raw_fd()),
Some(interactor_write_proxy.as_raw_fd()),
false,
)?;
interact_listener.spawn_with_sandbox(&mut interact_sandbox)?;
Expand All @@ -159,30 +162,38 @@ pub fn run_interact(
let mut interactor_exited = false;
let mut option_user_result: Option<RawRunResultInfo> = None;
loop {
let num_events = epoll.wait(&mut events, -1)?;
let num_events = epoll.wait(&mut events, EpollTimeout::NONE)?;
log::debug!("{} events found!", num_events);

for event in events.iter().take(num_events) {
log::debug!("Event: {:?}", event);
let fd = event.data() as RawFd;
if fd == user_exit_read {
if fd == user_exit_read.as_raw_fd() {
log::debug!("{:?} user fd exited", fd);
user_exited = true;
let exit_msg = read_msg_from_fd(fd)?;
option_user_result = exit_msg.option_run_result;
}
if fd == interactor_exit_read {
if fd == interactor_exit_read.as_raw_fd() {
log::debug!("{:?} interactor fd exited", fd);
interactor_exited = true;
let _interactor_result: ProcessExitMessage = read_msg_from_fd(fd)?;
}
if fd == proxy_read_user {
if fd == proxy_read_user.as_raw_fd() {
log::debug!("proxy_read_user {} fd read", fd);
pump_proxy_pipe(proxy_read_user, proxy_write_interactor, output_raw_fd)?;
pump_proxy_pipe(
proxy_read_user.as_raw_fd(),
proxy_write_interactor.as_raw_fd(),
output_raw_fd.as_raw_fd(),
)?;
}
if fd == proxy_read_interactor {
if fd == proxy_read_interactor.as_raw_fd() {
log::debug!("proxy_read_interactor {} fd read", fd);
pump_proxy_pipe(proxy_read_interactor, proxy_write_user, output_raw_fd)?;
pump_proxy_pipe(
proxy_read_interactor.as_raw_fd(),
proxy_write_user.as_raw_fd(),
output_raw_fd.as_raw_fd(),
)?;
}
}
if user_exited && interactor_exited {
Expand Down
1 change: 0 additions & 1 deletion judge-core/src/judge/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ pub fn check_user_result(
) -> Option<JudgeVerdict> {
if let Some(time_limit) = config.runtime.rlimit_configs.get_cpu_limit_duration() {
let run_time = get_run_time(raw_info);
// run_time is a little bit shorter than time_limit
if run_time > time_limit {
log::debug!("User program run time: {:?}", run_time);
log::debug!("Time limit: {:?}", time_limit);
Expand Down
6 changes: 4 additions & 2 deletions judge-core/src/run/process_listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::sandbox::{RawRunResultInfo, Sandbox};
use crate::error::JudgeCoreError;
use nix::unistd::{fork, write, ForkResult};
use serde_derive::{Deserialize, Serialize};
use std::os::unix::io::RawFd;
use std::os::{fd::BorrowedFd, unix::io::RawFd};

pub struct ProcessListener {
child_exit_fd: i32,
Expand Down Expand Up @@ -31,7 +31,9 @@ impl ProcessListener {
option_run_result,
};
let buf = serde_json::to_vec(&msg).expect("Serialize failed.");
write(self.child_exit_fd, &buf).unwrap();
// We should be really careful here
// not using OwnedFd here because it will close the fd
write(unsafe { BorrowedFd::borrow_raw(self.child_exit_fd) }, &buf).unwrap();
}
}

Expand Down

0 comments on commit 3c512b5

Please sign in to comment.