mirror of
https://github.com/MeiK2333/river.git
synced 2025-11-04 14:49:40 +08:00
常规更新
This commit is contained in:
parent
45af94494a
commit
14d67da8f3
@ -1,7 +1,7 @@
|
||||
use crate::river::judge_response::{JudgeResult, JudgeStatus};
|
||||
use crate::river::JudgeResponse;
|
||||
use libc::strerror;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::{CStr, NulError, OsString};
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::result;
|
||||
@ -12,6 +12,8 @@ pub enum Error {
|
||||
LanguageNotFound(i32),
|
||||
FileWriteError(io::Error),
|
||||
ChannelRecvError,
|
||||
StringToCStringError(NulError),
|
||||
OsStringToStringError(OsString),
|
||||
}
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
@ -6,21 +6,30 @@ use crate::river::{JudgeRequest, JudgeResponse};
|
||||
use std::path::Path;
|
||||
use tokio::fs;
|
||||
|
||||
impl JudgeResponse {
|
||||
fn new() -> JudgeResponse {
|
||||
JudgeResponse {
|
||||
time_used: 0,
|
||||
memory_used: 0,
|
||||
result: JudgeResult::Accepted as i32,
|
||||
errno: 0,
|
||||
exit_code: 0,
|
||||
stdout: "".into(),
|
||||
stderr: "".into(),
|
||||
errmsg: "".into(),
|
||||
status: JudgeStatus::Running as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn judger(request: &JudgeRequest) -> Result<JudgeResponse> {
|
||||
return Ok(JudgeResponse {
|
||||
time_used: request.time_limit,
|
||||
memory_used: 2,
|
||||
result: JudgeResult::Accepted as i32,
|
||||
errno: 0,
|
||||
exit_code: 0,
|
||||
stdout: "stdout".into(),
|
||||
stderr: "stderr".into(),
|
||||
errmsg: "".into(),
|
||||
status: JudgeStatus::Ended as i32,
|
||||
});
|
||||
let mut resp = JudgeResponse::new();
|
||||
resp.time_used = request.time_limit;
|
||||
return Ok(resp);
|
||||
}
|
||||
|
||||
pub async fn compile(request: &JudgeRequest, path: &Path) -> Result<JudgeResponse> {
|
||||
let mut resp = JudgeResponse::new();
|
||||
// 写入代码
|
||||
let filename = match Language::from_i32(request.language) {
|
||||
Some(Language::C) => "main.c",
|
||||
@ -36,21 +45,29 @@ pub async fn compile(request: &JudgeRequest, path: &Path) -> Result<JudgeRespons
|
||||
return Err(Error::FileWriteError(e));
|
||||
};
|
||||
|
||||
let process = Process::new();
|
||||
let status = process.await?;
|
||||
println!("{}", status.exit_code);
|
||||
let mut process = Process::new();
|
||||
let cmd = match Language::from_i32(request.language) {
|
||||
Some(Language::C) => "gcc main.c",
|
||||
Some(Language::Cpp) => "g++ main.cpp",
|
||||
Some(Language::Python) => "/usr/bin/python3 -m compileall main.py",
|
||||
Some(Language::Rust) => "rustc main.rs",
|
||||
// 无需编译的语言直接返回
|
||||
Some(Language::Node) => return Ok(resp),
|
||||
Some(Language::TypeScript) => "tsc",
|
||||
Some(Language::Go) => "main.go",
|
||||
None => return Err(Error::LanguageNotFound(request.language)),
|
||||
};
|
||||
process.cmd = cmd.to_string();
|
||||
process.workdir = path.to_path_buf();
|
||||
process.time_limit = request.time_limit;
|
||||
process.memory_limit = request.memory_limit;
|
||||
|
||||
return Ok(JudgeResponse {
|
||||
time_used: request.time_limit,
|
||||
memory_used: 2,
|
||||
result: JudgeResult::Accepted as i32,
|
||||
errno: 0,
|
||||
exit_code: 0,
|
||||
stdout: "stdout".into(),
|
||||
stderr: "stderr".into(),
|
||||
errmsg: "".into(),
|
||||
status: JudgeStatus::Ended as i32,
|
||||
});
|
||||
let status = process.await?;
|
||||
if status.exit_code != 0 {
|
||||
resp.result = JudgeResult::CompileError as i32;
|
||||
resp.status = JudgeStatus::Ended as i32;
|
||||
}
|
||||
return Ok(resp);
|
||||
}
|
||||
|
||||
pub fn pending() -> JudgeResponse {
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
use super::error::{Error, Result};
|
||||
use libc;
|
||||
use std::env;
|
||||
use std::ffi::CString;
|
||||
use std::future::Future;
|
||||
use std::mem;
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
use std::ptr;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::task::{Context, Poll};
|
||||
@ -11,6 +16,7 @@ use std::time::SystemTime;
|
||||
#[derive(Clone)]
|
||||
pub struct Process {
|
||||
pub pid: i32,
|
||||
pub workdir: PathBuf,
|
||||
pub time_limit: i32,
|
||||
pub memory_limit: i32,
|
||||
pub stdin_fd: i32,
|
||||
@ -32,6 +38,7 @@ impl Process {
|
||||
stdout_fd: -1,
|
||||
stderr_fd: -1,
|
||||
cmd: "".to_string(),
|
||||
workdir: PathBuf::from(""),
|
||||
tx: Arc::new(Mutex::new(tx)),
|
||||
rx: Arc::new(Mutex::new(rx)),
|
||||
}
|
||||
@ -91,14 +98,88 @@ impl Future for Process {
|
||||
}
|
||||
}
|
||||
|
||||
fn run(_process: Process) {
|
||||
unsafe {
|
||||
// TODO
|
||||
println!("run");
|
||||
libc::exit(1);
|
||||
pub struct ExecArgs {
|
||||
pub pathname: *const libc::c_char,
|
||||
pub argv: *const *const libc::c_char,
|
||||
pub envp: *const *const libc::c_char,
|
||||
}
|
||||
|
||||
impl ExecArgs {
|
||||
fn build(cmd: &String) -> Result<ExecArgs> {
|
||||
let cmds: Vec<&str> = cmd.split_whitespace().collect();
|
||||
let pathname = cmds[0].clone();
|
||||
let pathname_str = match CString::new(pathname) {
|
||||
Ok(value) => value,
|
||||
Err(err) => return Err(Error::StringToCStringError(err)),
|
||||
};
|
||||
let pathname = pathname_str.as_ptr();
|
||||
|
||||
let mut argv_vec: Vec<*const libc::c_char> = vec![];
|
||||
for item in cmds.iter() {
|
||||
let cstr = match CString::new(item.clone()) {
|
||||
Ok(value) => value,
|
||||
Err(err) => return Err(Error::StringToCStringError(err)),
|
||||
};
|
||||
let cptr = cstr.as_ptr();
|
||||
// 需要使用 mem::forget 来标记
|
||||
// 否则在此次循环结束后,cstr 就会被回收,后续 exec 函数无法通过指针获取到字符串内容
|
||||
mem::forget(cstr);
|
||||
argv_vec.push(cptr);
|
||||
}
|
||||
// argv 与 envp 的参数需要使用 NULL 来标记结束
|
||||
argv_vec.push(ptr::null());
|
||||
let argv: *const *const libc::c_char = argv_vec.as_ptr() as *const *const libc::c_char;
|
||||
|
||||
// env 环境变量传递当前进程环境变量
|
||||
let mut envp_vec: Vec<*const libc::c_char> = vec![];
|
||||
for (key, value) in env::vars_os() {
|
||||
let mut key = match key.to_str() {
|
||||
Some(val) => val.to_string(),
|
||||
None => return Err(Error::OsStringToStringError(key)),
|
||||
};
|
||||
let value = match value.to_str() {
|
||||
Some(val) => val.to_string(),
|
||||
None => return Err(Error::OsStringToStringError(value)),
|
||||
};
|
||||
key.push_str("=");
|
||||
key.push_str(&value);
|
||||
let cstr = match CString::new(key) {
|
||||
Ok(value) => value,
|
||||
Err(err) => return Err(Error::StringToCStringError(err)),
|
||||
};
|
||||
let cptr = cstr.as_ptr();
|
||||
// 需要使用 mem::forget 来标记
|
||||
// 否则在此次循环结束后,cstr 就会被回收,后续 exec 函数无法通过指针获取到字符串内容
|
||||
mem::forget(cstr);
|
||||
envp_vec.push(cptr);
|
||||
}
|
||||
envp_vec.push(ptr::null());
|
||||
let envp = envp_vec.as_ptr() as *const *const libc::c_char;
|
||||
|
||||
mem::forget(pathname_str);
|
||||
mem::forget(argv_vec);
|
||||
mem::forget(envp_vec);
|
||||
Ok(ExecArgs {
|
||||
pathname,
|
||||
argv,
|
||||
envp,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn run(process: Process) {
|
||||
// 子进程里崩溃也无法返回,崩溃就直接崩溃了
|
||||
let exec_args = ExecArgs::build(&process.cmd).unwrap();
|
||||
// 修改工作目录
|
||||
env::set_current_dir(process.workdir).unwrap();
|
||||
println!("{}", process.cmd);
|
||||
unsafe {
|
||||
// TODO: 资源限制等
|
||||
libc::execve(exec_args.pathname, exec_args.argv, exec_args.envp);
|
||||
}
|
||||
panic!("How dare you!");
|
||||
}
|
||||
|
||||
fn wait(pid: i32) -> ProcessStatus {
|
||||
let start = SystemTime::now();
|
||||
let mut status = 0;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user