From a4fa1593701ed2ca6e72604b2df034ba73e7f5a1 Mon Sep 17 00:00:00 2001 From: MeiK Date: Tue, 8 Sep 2020 16:21:57 +0800 Subject: [PATCH] Update --- src/error.rs | 1 + src/judger.rs | 4 ++-- src/main.rs | 1 + src/process.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/error.rs b/src/error.rs index f833bbb..cd338e7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -17,6 +17,7 @@ pub enum Error { OsStringToStringError(OsString), RemoveFileError(PathBuf), UnknownRequestData, + RequestDataNotFound, } pub type Result = result::Result; diff --git a/src/judger.rs b/src/judger.rs index 019c355..a5d88d7 100644 --- a/src/judger.rs +++ b/src/judger.rs @@ -68,6 +68,7 @@ pub async fn judger(request: &JudgeRequest, data: &JudgeData, path: &Path) -> Re pub async fn compile(request: &JudgeRequest, data: &CompileData, path: &Path) -> Result { let mut resp = JudgeResponse::new(); + resp.status = JudgeStatus::Ended as i32; // 写入代码 let filename = match Language::from_i32(request.language) { Some(Language::C) => "main.c", @@ -105,9 +106,8 @@ pub async fn compile(request: &JudgeRequest, data: &CompileData, path: &Path) -> let status = process.await?; if status.exit_code != 0 { resp.set_process_status(&status); - resp.errmsg = status.stdout; + resp.errmsg = format!("{}{}", status.stdout, status.stderr); resp.result = JudgeResult::CompileError as i32; - resp.status = JudgeStatus::Ended as i32; } Ok(resp) } diff --git a/src/main.rs b/src/main.rs index 8c2dc22..6356b7a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,6 +54,7 @@ impl River for RiverService { let result = match &req.data { Some(Data::CompileData(data)) => judger::compile(&req, &data, &pwd.path()).await, Some(Data::JudgeData(data)) => judger::judger(&req, &data, &pwd.path()).await, + None => Err(error::Error::RequestDataNotFound), _ => Err(error::Error::UnknownRequestData), }; let result = match result { diff --git a/src/process.rs b/src/process.rs index 374759a..c9e4404 100644 --- a/src/process.rs +++ b/src/process.rs @@ -44,6 +44,48 @@ impl Process { pub fn set_pid(&mut self, pid: i32) { self.pid = pid; } + + #[allow(dead_code)] + #[allow(unused_variables)] + // 为进程设置 stdin 的数据 + pub fn set_stdin(in_data: &Vec) { + // TODO + } + + #[allow(dead_code)] + #[allow(unused_variables)] + // 从 stdout 中读取指定长度的内容 + pub fn read_stdout(len: i32) { + // TODO + } + + #[allow(dead_code)] + #[allow(unused_variables)] + // 从 stderr 中读取指定长度的内容 + pub fn read_stderr(len: i32) { + // TODO + } +} + +impl Drop for Process { + fn drop(&mut self) { + if self.pid > 0 { + let mut status = 0; + let pid; + unsafe { + pid = libc::waitpid(self.pid, &mut status, libc::WNOHANG); + } + // > 0: 对应子进程退出 + // = 0: 对应子进程存在但未退出 + // 如果在运行过程中上层异常中断,则需要 kill 子进程并回收资源 + if pid >= 0 { + unsafe { + libc::kill(self.pid, 9); + libc::waitpid(self.pid, &mut status, 0); + } + } + } + } } impl Future for Process { @@ -65,7 +107,7 @@ impl Future for Process { run(process_clone); } else if pid > 0 { tx.send(pid).unwrap(); - let status = wait(pid, process_clone.workdir); + let status = wait(pid, &process_clone.workdir); let status_tx = process_clone.tx.lock().unwrap(); status_tx.send(status).unwrap(); waker.wake(); @@ -190,7 +232,7 @@ fn run(process: Process) { // 子进程里崩溃也无法返回,崩溃就直接崩溃了 let exec_args = ExecArgs::build(&process.cmd).unwrap(); // 修改工作目录 - env::set_current_dir(process.workdir).unwrap(); + env::set_current_dir(&process.workdir).unwrap(); let mut rl = libc::rlimit { rlim_cur: 0, rlim_max: 0, @@ -208,7 +250,7 @@ fn run(process: Process) { }; unsafe { // 重定向文件描述符 - if let Some(file) = process.stdin_file { + if let Some(file) = &process.stdin_file { let filename = file.to_str().unwrap(); dup(&filename, libc::STDIN_FILENO, libc::O_RDONLY, 0o644) } @@ -274,7 +316,7 @@ unsafe fn dup(filename: &str, to: libc::c_int, flag: libc::c_int, mode: libc::c_ } } -fn wait(pid: i32, workdir: PathBuf) -> ProcessStatus { +fn wait(pid: i32, workdir: &PathBuf) -> ProcessStatus { let start = SystemTime::now(); let mut status = 0; let mut rusage = libc::rusage {