mirror of
https://github.com/MeiK2333/river.git
synced 2025-11-04 14:49:40 +08:00
更新输入输出的机制
This commit is contained in:
parent
177e228ec2
commit
f84c5d12fc
@ -39,9 +39,7 @@ pub async fn judger(
|
|||||||
Some(Language::Go) => "./a.out",
|
Some(Language::Go) => "./a.out",
|
||||||
None => return Err(Error::LanguageNotFound(request.language)),
|
None => return Err(Error::LanguageNotFound(request.language)),
|
||||||
};
|
};
|
||||||
let mut process = Process::new(cmd.to_string(), path.to_path_buf())?;
|
let mut process = Process::new(cmd.to_string(), path.to_path_buf(), data.time_limit, data.memory_limit)?;
|
||||||
process.time_limit = data.time_limit;
|
|
||||||
process.memory_limit = data.memory_limit;
|
|
||||||
|
|
||||||
// 设置输入数据
|
// 设置输入数据
|
||||||
process.set_stdin(&data.in_data)?;
|
process.set_stdin(&data.in_data)?;
|
||||||
@ -94,10 +92,8 @@ pub async fn compile(
|
|||||||
Some(Language::Go) => "/usr/bin/go build -ldflags \"-s -w\" main.go",
|
Some(Language::Go) => "/usr/bin/go build -ldflags \"-s -w\" main.go",
|
||||||
None => return Err(Error::LanguageNotFound(request.language)),
|
None => return Err(Error::LanguageNotFound(request.language)),
|
||||||
};
|
};
|
||||||
let mut process = Process::new(cmd.to_string(), path.to_path_buf())?;
|
|
||||||
// 编译的资源限制为固定的
|
// 编译的资源限制为固定的
|
||||||
process.time_limit = 10000;
|
let process = Process::new(cmd.to_string(), path.to_path_buf(), 10000, 64 * 1024)?;
|
||||||
process.memory_limit = 64 * 1024;
|
|
||||||
|
|
||||||
let status = process.await?;
|
let status = process.await?;
|
||||||
if status.exit_code != 0 {
|
if status.exit_code != 0 {
|
||||||
|
|||||||
@ -20,8 +20,8 @@ use std::time::SystemTime;
|
|||||||
pub struct Process {
|
pub struct Process {
|
||||||
pub pid: i32,
|
pub pid: i32,
|
||||||
pub workdir: PathBuf,
|
pub workdir: PathBuf,
|
||||||
pub time_limit: i32,
|
time_limit: i32,
|
||||||
pub memory_limit: i32,
|
memory_limit: i32,
|
||||||
stdin_fd: Option<i32>,
|
stdin_fd: Option<i32>,
|
||||||
stdout_fd: i32,
|
stdout_fd: i32,
|
||||||
stderr_fd: i32,
|
stderr_fd: i32,
|
||||||
@ -42,7 +42,12 @@ fn path_buf_str(path_buf: &PathBuf) -> Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Process {
|
impl Process {
|
||||||
pub fn new(cmd: String, workdir: PathBuf) -> Result<Process> {
|
pub fn new(
|
||||||
|
cmd: String,
|
||||||
|
workdir: PathBuf,
|
||||||
|
time_limit: i32,
|
||||||
|
memory_limit: i32,
|
||||||
|
) -> Result<Process> {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
let memfile = path_buf_str(&workdir)?;
|
let memfile = path_buf_str(&workdir)?;
|
||||||
@ -57,22 +62,22 @@ impl Process {
|
|||||||
let stdout_fd = unsafe {
|
let stdout_fd = unsafe {
|
||||||
libc::shm_open(
|
libc::shm_open(
|
||||||
outfile.as_ptr(),
|
outfile.as_ptr(),
|
||||||
libc::O_RDWR | libc::O_CREAT | libc::O_TRUNC,
|
libc::O_RDWR | libc::O_CREAT,
|
||||||
0,
|
libc::S_IRUSR | libc::S_IWUSR,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let stderr_fd = unsafe {
|
let stderr_fd = unsafe {
|
||||||
libc::shm_open(
|
libc::shm_open(
|
||||||
errfile.as_ptr(),
|
errfile.as_ptr(),
|
||||||
libc::O_RDWR | libc::O_CREAT | libc::O_TRUNC,
|
libc::O_RDWR | libc::O_CREAT,
|
||||||
0,
|
libc::S_IRUSR | libc::S_IWUSR,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Process {
|
Ok(Process {
|
||||||
pid: -1,
|
pid: -1,
|
||||||
time_limit: -1,
|
time_limit: time_limit,
|
||||||
memory_limit: -1,
|
memory_limit: memory_limit,
|
||||||
stdin_fd: None,
|
stdin_fd: None,
|
||||||
stdout_fd: stdout_fd,
|
stdout_fd: stdout_fd,
|
||||||
stderr_fd: stderr_fd,
|
stderr_fd: stderr_fd,
|
||||||
@ -94,8 +99,8 @@ impl Process {
|
|||||||
let fd = unsafe {
|
let fd = unsafe {
|
||||||
libc::shm_open(
|
libc::shm_open(
|
||||||
CString::new(memfile).unwrap().as_ptr(),
|
CString::new(memfile).unwrap().as_ptr(),
|
||||||
libc::O_RDWR | libc::O_CREAT | libc::O_TRUNC,
|
libc::O_RDWR | libc::O_CREAT,
|
||||||
0,
|
libc::S_IRUSR | libc::S_IWUSR,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
if fd <= 0 {
|
if fd <= 0 {
|
||||||
@ -132,9 +137,14 @@ impl Process {
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
// 从 stdout 中读取指定长度的内容
|
// TODO: 修改读取方式
|
||||||
pub fn read_stdout(&mut self, len: i32) {
|
// 从 stdout 中读取内容
|
||||||
// TODO
|
pub fn read_stdout(self) -> [u8; 1024] {
|
||||||
|
let mut buf: [u8; 1024] = [0; 1024];
|
||||||
|
let size = unsafe {
|
||||||
|
libc::read(self.stdout_fd, buf.as_mut_ptr() as *mut c_void, 1024);
|
||||||
|
};
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -172,6 +182,14 @@ impl Drop for Process {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 清理 stdout 和 stderr 的空间
|
||||||
|
let memfile = path_buf_str(&self.workdir).unwrap();
|
||||||
|
let outfile = CString::new(format!("{}{}", "stdout", memfile)).unwrap();
|
||||||
|
let errfile = CString::new(format!("{}{}", "stderr", memfile)).unwrap();
|
||||||
|
unsafe {
|
||||||
|
libc::shm_unlink(CString::new(outfile).unwrap().as_ptr());
|
||||||
|
libc::shm_unlink(CString::new(errfile).unwrap().as_ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,8 +434,17 @@ impl Process {
|
|||||||
ru_nivcsw: 0 as libc::c_long,
|
ru_nivcsw: 0 as libc::c_long,
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let val = libc::wait4(pid, &mut status, 0, &mut rusage);
|
// 等待子进程结束
|
||||||
if val < 0 {
|
if libc::wait4(pid, &mut status, 0, &mut rusage) < 0 {
|
||||||
|
eprintln!("{:?}", io::Error::last_os_error().raw_os_error());
|
||||||
|
panic!("How dare you!");
|
||||||
|
}
|
||||||
|
// 重置输出偏移量
|
||||||
|
if libc::lseek(self.stdout_fd, 0, libc::SEEK_SET) < 0 {
|
||||||
|
eprintln!("{:?}", io::Error::last_os_error().raw_os_error());
|
||||||
|
panic!("How dare you!");
|
||||||
|
}
|
||||||
|
if libc::lseek(self.stderr_fd, 0, libc::SEEK_SET) < 0 {
|
||||||
eprintln!("{:?}", io::Error::last_os_error().raw_os_error());
|
eprintln!("{:?}", io::Error::last_os_error().raw_os_error());
|
||||||
panic!("How dare you!");
|
panic!("How dare you!");
|
||||||
}
|
}
|
||||||
@ -476,6 +503,7 @@ pub struct ProcessStatus {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::process::Process;
|
use crate::process::Process;
|
||||||
|
use std::ffi::CString;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use tempfile::tempdir_in;
|
use tempfile::tempdir_in;
|
||||||
|
|
||||||
@ -488,12 +516,20 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn run() {
|
async fn run() {
|
||||||
let cmd = String::from("/bin/echo hello world");
|
let cmd = String::from("/bin/echo hello");
|
||||||
let pwd = tempdir_in("./runner").unwrap().into_path();
|
let pwd = tempdir_in("./runner").unwrap().into_path();
|
||||||
let path = pwd.to_str().unwrap();
|
let path = pwd.to_str().unwrap();
|
||||||
let process = Process::new(cmd, pwd.clone()).unwrap();
|
let process = Process::new(cmd, pwd.clone(), 1000, 65535).unwrap();
|
||||||
|
let p = process.clone();
|
||||||
let status = process.await.unwrap();
|
let status = process.await.unwrap();
|
||||||
fs::remove_dir_all(path).unwrap();
|
fs::remove_dir_all(path).unwrap();
|
||||||
assert_eq!(status.exit_code, 0);
|
assert_eq!(status.exit_code, 0);
|
||||||
|
let mut buf = p.read_stdout();
|
||||||
|
unsafe {
|
||||||
|
libc::printf(
|
||||||
|
CString::new("c string = %s\n").unwrap().as_ptr(),
|
||||||
|
buf.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user