mirror of
https://github.com/MeiK2333/river.git
synced 2025-11-04 14:49:40 +08:00
Update
This commit is contained in:
parent
7931f6b2bc
commit
55d090af9d
18
src/error.rs
18
src/error.rs
@ -1,5 +1,7 @@
|
|||||||
use crate::river::judge_response::{JudgeResult, JudgeStatus};
|
use crate::river::judge_response::{JudgeResult, JudgeStatus};
|
||||||
use crate::river::JudgeResponse;
|
use crate::river::JudgeResponse;
|
||||||
|
use libc::strerror;
|
||||||
|
use std::ffi::CStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::result;
|
use std::result;
|
||||||
@ -9,13 +11,29 @@ pub enum Error {
|
|||||||
CreateTempDirError(io::Error),
|
CreateTempDirError(io::Error),
|
||||||
LanguageNotFound(i32),
|
LanguageNotFound(i32),
|
||||||
FileWriteError(io::Error),
|
FileWriteError(io::Error),
|
||||||
|
ForkError(Option<i32>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
|
pub fn errno_str(errno: Option<i32>) -> String {
|
||||||
|
match errno {
|
||||||
|
Some(no) => {
|
||||||
|
let stre = unsafe { strerror(no) };
|
||||||
|
let c_str: &CStr = unsafe { CStr::from_ptr(stre) };
|
||||||
|
c_str.to_str().unwrap().to_string()
|
||||||
|
}
|
||||||
|
_ => "Unknown Error!".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
|
Error::ForkError(errno) => {
|
||||||
|
let reason = errno_str(errno);
|
||||||
|
write!(f, "ForkError: {}", reason)
|
||||||
|
}
|
||||||
_ => write!(f, "{:?}", self),
|
_ => write!(f, "{:?}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,6 @@ pub async fn compile(request: &JudgeRequest, path: &Path) -> Result<JudgeRespons
|
|||||||
Some(Language::Go) => "main.go",
|
Some(Language::Go) => "main.go",
|
||||||
None => return Err(Error::LanguageNotFound(request.language)),
|
None => return Err(Error::LanguageNotFound(request.language)),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = fs::write(path.join(filename), request.code.clone()).await {
|
if let Err(e) = fs::write(path.join(filename), request.code.clone()).await {
|
||||||
return Err(Error::FileWriteError(e));
|
return Err(Error::FileWriteError(e));
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,41 +1,91 @@
|
|||||||
|
use super::error::{Error, Result};
|
||||||
use libc;
|
use libc;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
use std::io;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Process {
|
pub struct Process {
|
||||||
pub pid: i32,
|
pub pid: i32,
|
||||||
pub time_limit: i32,
|
pub time_limit: i32,
|
||||||
pub read_time_limit: i32,
|
|
||||||
pub memory_limit: i32,
|
pub memory_limit: i32,
|
||||||
pub stdin_fd: i32,
|
pub stdin_fd: i32,
|
||||||
pub stdout_fd: i32,
|
pub stdout_fd: i32,
|
||||||
pub stderr_fd: i32,
|
pub stderr_fd: i32,
|
||||||
pub cmd: str,
|
pub cmd: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Process {
|
||||||
|
pub fn new() -> Process {
|
||||||
|
Process {
|
||||||
|
pid: -1,
|
||||||
|
time_limit: -1,
|
||||||
|
memory_limit: -1,
|
||||||
|
stdin_fd: -1,
|
||||||
|
stdout_fd: -1,
|
||||||
|
stderr_fd: -1,
|
||||||
|
cmd: "".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn set_pid(&mut self, pid: i32) {
|
||||||
|
self.pid = pid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Future for Process {
|
impl Future for Process {
|
||||||
type Output = &'static str;
|
type Output = Result<ProcessStatus>;
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<&'static str> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<ProcessStatus>> {
|
||||||
let mut status = 0;
|
// pid == -1 时为第一次触发,此时开始运行
|
||||||
unsafe {
|
// 直到进程执行完毕, wake 通知进入下次检查
|
||||||
// TODO: fork、修改用户、组、设置限制,exec 等等
|
if self.pid == -1 {
|
||||||
// TODO: seccomp 等保证安全
|
let pid;
|
||||||
let _pid = libc::waitpid(self.pid, &mut status, libc::WNOHANG);
|
unsafe {
|
||||||
|
pid = libc::fork();
|
||||||
|
}
|
||||||
|
if pid == 0 {
|
||||||
|
// 子进程
|
||||||
|
// TODO: fork、修改用户、组、设置限制,exec 等等
|
||||||
|
// TODO: seccomp 等保证安全
|
||||||
|
let process = Pin::into_inner(self).clone();
|
||||||
|
run(process);
|
||||||
|
} else if pid > 0 {
|
||||||
|
// 父进程
|
||||||
|
self.as_mut().set_pid(pid);
|
||||||
|
let waker = cx.waker().clone();
|
||||||
|
let pid = self.pid;
|
||||||
|
|
||||||
|
thread::spawn(move || {
|
||||||
|
// 等待子进程结束
|
||||||
|
wait(pid);
|
||||||
|
// 触发唤醒异步
|
||||||
|
waker.wake();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 出错
|
||||||
|
return Poll::Ready(Err(Error::ForkError(
|
||||||
|
io::Error::last_os_error().raw_os_error(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
return Poll::Pending;
|
||||||
|
} else {
|
||||||
|
// 子进程结束后被唤醒
|
||||||
|
// 收集运行信息,返回数据,结束异步
|
||||||
|
wait(self.pid);
|
||||||
|
// TODO: Poll::Ready
|
||||||
|
return Poll::Pending;
|
||||||
}
|
}
|
||||||
if status != 0 {
|
|
||||||
return Poll::Ready("");
|
|
||||||
}
|
|
||||||
let waker = cx.waker().clone();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
thread::sleep(Duration::from_millis(3000));
|
|
||||||
waker.wake();
|
|
||||||
});
|
|
||||||
|
|
||||||
Poll::Pending
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run(process: Process) {}
|
||||||
|
|
||||||
|
fn wait(pid: i32) {}
|
||||||
|
|
||||||
|
pub struct ProcessStatus {
|
||||||
|
pub rusage: libc::rusage,
|
||||||
|
pub exit_code: i32,
|
||||||
|
pub status: i32,
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user