Skip to content

Commit

Permalink
refactor: ♻️ minor judger refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Eason0729 committed Dec 21, 2023
1 parent 645b020 commit 4094f3a
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 7 deletions.
1 change: 1 addition & 0 deletions judger/src/langs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod prelude {
pub use super::artifact::*;
}

// Error incur from server setup
#[derive(Error, Debug)]
pub enum InitError {
#[error("`{0}`")]
Expand Down
1 change: 1 addition & 0 deletions judger/src/sandbox/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ impl<'a> Drop for Container<'a> {
}

impl<'a> Container<'a> {
/// execute command inisde container
pub async fn execute(&self, args: &[&str], limit: Limit) -> Result<RunningProc, Error> {
let config = CONFIG.get().unwrap();

Expand Down
6 changes: 3 additions & 3 deletions judger/src/sandbox/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ impl RunningProc {
}
};
// because in the senario of out of memory, process will be either exit with code
// 11(unable to allocate memory) or kill by signal(if oom killer is enable)
// , so we need to check if it is oom
// 11(unable to allocate memory) or kill by signal, whichever comes first,
// so we need to check if it is oom
if self.limiter.check_oom() {
status = ExitStatus::MemExhausted;
}
Expand All @@ -93,7 +93,7 @@ impl RunningProc {
return Err(Error::BufferFull);
}

let (cpu, mem) = self.limiter.status().await;
let (cpu, mem) = self.limiter.statistics().await;
let output_limit = config.platform.output_limit as u64;

let _memory_holder = self._memory_holder.downgrade(output_limit);
Expand Down
18 changes: 17 additions & 1 deletion judger/src/sandbox/utils/limiter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ use crate::init::config::CONFIG;
pub mod cpu;
pub mod mem;

/// reason for a process terminate by limiter
pub enum LimitReason {
Cpu,
Mem,
SysMem,
}

/// object for limit resource usage and report it
///
/// resource monitoring start immediately after the initialized
// be aware that cgroup-rs reset all number of the cgroup to zero,
// so limiter should be initialize after `cgroup_rs::Cgroup`
pub struct Limiter {
task: JoinHandle<()>,
state: Arc<AtomicPtr<LimiterState>>,
Expand All @@ -31,6 +37,9 @@ pub struct Limiter {
cg: Cgroup,
}

/// state for CpuStatistics, MemStatistics
// why not just make cpu and mem a object and make those own its state?
// because monitoring take time, and we expect cpu and mem not to spawn its own tokio thread
#[derive(Default)]
struct LimiterState {
cpu: CpuStatistics,
Expand All @@ -47,6 +56,7 @@ impl Drop for Limiter {
}

impl Limiter {
/// create limiter with limit
pub fn new(cg_name: &str, limit: Limit) -> Result<Self, Error> {
log::trace!("Creating new limiter for {}", cg_name);
let (tx, rx) = oneshot::channel();
Expand Down Expand Up @@ -128,10 +138,14 @@ impl Limiter {
cg: cg2,
})
}
/// check if oom
///
/// It expose its internal state(use with care), callee should have explaination for usage
pub fn check_oom(&mut self) -> bool {
MemStatistics::from_cgroup(&self.cg).oom
}
pub async fn status(self) -> (CpuStatistics, MemStatistics) {
/// yield statistics, consume self
pub async fn statistics(self) -> (CpuStatistics, MemStatistics) {
let config = CONFIG.get().unwrap();

if !config.kernel.tickless {
Expand All @@ -146,6 +160,8 @@ impl Limiter {

(stat.cpu.clone(), stat.mem.clone())
}
/// wait for resouce exhausted
// it's reverse control flow, subject to change
pub fn wait_exhausted(&mut self) -> Receiver<LimitReason> {
self.limit_oneshot
.take()
Expand Down
6 changes: 3 additions & 3 deletions judger/src/sandbox/utils/nsjail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ use crate::init::config::CONFIG;

use super::super::Error;

// Nsjail abstraction, don't implement any meaningful logic
// Just a wrapper for nsjail

/// Nsjail abstraction, don't implement any meaningful logic
///
/// Just setup args and wrap for Mutex<Child> and automatic kill process when drop
pub struct LimitBuilder {
cmds: Vec<Cow<'static, str>>,
}
Expand Down
1 change: 1 addition & 0 deletions judger/src/sandbox/utils/semaphore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub struct MemoryStatistic {
}

/// A Semaphore for large buffer accounting
///
/// because tokio::sync::Semaphore default to u32 for inner type
#[derive(Clone)]
pub struct MemorySemaphore(Arc<Mutex<MemorySemaphoreInner>>);
Expand Down

0 comments on commit 4094f3a

Please sign in to comment.