diff --git a/judger/src/langs/mod.rs b/judger/src/langs/mod.rs index 9406ca88..a1fdd8fb 100644 --- a/judger/src/langs/mod.rs +++ b/judger/src/langs/mod.rs @@ -9,6 +9,7 @@ pub mod prelude { pub use super::artifact::*; } +// Error incur from server setup #[derive(Error, Debug)] pub enum InitError { #[error("`{0}`")] diff --git a/judger/src/sandbox/container.rs b/judger/src/sandbox/container.rs index 6e4ca766..2cf003d6 100644 --- a/judger/src/sandbox/container.rs +++ b/judger/src/sandbox/container.rs @@ -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 { let config = CONFIG.get().unwrap(); diff --git a/judger/src/sandbox/process.rs b/judger/src/sandbox/process.rs index 5879723c..f3c8dcf8 100644 --- a/judger/src/sandbox/process.rs +++ b/judger/src/sandbox/process.rs @@ -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; } @@ -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); diff --git a/judger/src/sandbox/utils/limiter/mod.rs b/judger/src/sandbox/utils/limiter/mod.rs index 5a470e09..f269b897 100644 --- a/judger/src/sandbox/utils/limiter/mod.rs +++ b/judger/src/sandbox/utils/limiter/mod.rs @@ -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>, @@ -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, @@ -47,6 +56,7 @@ impl Drop for Limiter { } impl Limiter { + /// create limiter with limit pub fn new(cg_name: &str, limit: Limit) -> Result { log::trace!("Creating new limiter for {}", cg_name); let (tx, rx) = oneshot::channel(); @@ -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 { @@ -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 { self.limit_oneshot .take() diff --git a/judger/src/sandbox/utils/nsjail.rs b/judger/src/sandbox/utils/nsjail.rs index 97bd1e43..effe5e5e 100644 --- a/judger/src/sandbox/utils/nsjail.rs +++ b/judger/src/sandbox/utils/nsjail.rs @@ -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 and automatic kill process when drop pub struct LimitBuilder { cmds: Vec>, } diff --git a/judger/src/sandbox/utils/semaphore.rs b/judger/src/sandbox/utils/semaphore.rs index a3de63b8..eb515168 100644 --- a/judger/src/sandbox/utils/semaphore.rs +++ b/judger/src/sandbox/utils/semaphore.rs @@ -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>);