mirror of
https://github.com/MeiK2333/river.git
synced 2025-11-04 14:49:40 +08:00
add language: java
This commit is contained in:
parent
c582bc8757
commit
26d8727db7
@ -17,6 +17,8 @@ tempfile = "3"
|
||||
libc = "0.2.76"
|
||||
log = "0.4.0"
|
||||
env_logger = "0.8.1"
|
||||
nix = "0.19.0"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build ={ version = "0.3" }
|
||||
cc = "1.0"
|
||||
1
build.rs
1
build.rs
@ -1,4 +1,5 @@
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
tonic_build::compile_protos("proto/river.proto")?;
|
||||
cc::Build::new().file("src/memory.c").compile("memory");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
5
example/java/1000/Main.java
Normal file
5
example/java/1000/Main.java
Normal file
@ -0,0 +1,5 @@
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello World!");
|
||||
}
|
||||
}
|
||||
0
example/java/1000/in.txt
Normal file
0
example/java/1000/in.txt
Normal file
1
example/java/1000/out.txt
Normal file
1
example/java/1000/out.txt
Normal file
@ -0,0 +1 @@
|
||||
Hello World!
|
||||
12
example/java/1001/Main.java
Normal file
12
example/java/1001/Main.java
Normal file
@ -0,0 +1,12 @@
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Scanner reader = new Scanner(System.in);
|
||||
int a, b;
|
||||
a = reader.nextInt();
|
||||
b = reader.nextInt();
|
||||
System.out.println(a + b);
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
1
example/java/1001/in.txt
Normal file
1
example/java/1001/in.txt
Normal file
@ -0,0 +1 @@
|
||||
2 3
|
||||
1
example/java/1001/out.txt
Normal file
1
example/java/1001/out.txt
Normal file
@ -0,0 +1 @@
|
||||
5
|
||||
@ -13,6 +13,8 @@ def judge(path, language):
|
||||
filename = "main.cpp"
|
||||
elif language == river_pb2.Python:
|
||||
filename = "main.py"
|
||||
elif language == river_pb2.Java:
|
||||
filename = "Main.java"
|
||||
with open(path.joinpath(filename), "rb") as fr:
|
||||
code = fr.read()
|
||||
with open(path.joinpath("in.txt"), "rb") as fr:
|
||||
@ -25,19 +27,30 @@ def judge(path, language):
|
||||
judge_type=river_pb2.Standard,
|
||||
compile_data=river_pb2.CompileData(code=code),
|
||||
)
|
||||
# if language == river_pb2.Java:
|
||||
# import time
|
||||
# time.sleep(1000)
|
||||
# judge
|
||||
yield river_pb2.JudgeRequest(
|
||||
language=language,
|
||||
judge_type=river_pb2.Standard,
|
||||
judge_data=river_pb2.JudgeData(
|
||||
in_data=in_data, out_data=out_data, time_limit=1000, memory_limit=65535
|
||||
in_data=in_data, out_data=out_data, time_limit=10000, memory_limit=65535
|
||||
),
|
||||
)
|
||||
# if language == river_pb2.Java:
|
||||
# import time
|
||||
# time.sleep(1000)
|
||||
|
||||
|
||||
def run():
|
||||
with grpc.insecure_channel("localhost:4003") as channel:
|
||||
stub = river_pb2_grpc.RiverStub(channel)
|
||||
for path in Path("java").iterdir():
|
||||
print(f"开始评测 {path}")
|
||||
for item in stub.Judge(judge(path, river_pb2.Java)):
|
||||
print(item)
|
||||
print(f"{path} 评测完成")
|
||||
for path in Path("c").iterdir():
|
||||
print(f"开始评测 {path}")
|
||||
for item in stub.Judge(judge(path, river_pb2.C)):
|
||||
|
||||
16
src/allow.rs
16
src/allow.rs
@ -7,17 +7,22 @@ pub fn gen_rules() -> Vec<SyscallRuleSet> {
|
||||
allow_syscall(libc::SYS_arch_prctl),
|
||||
// allow_syscall(libc::SYS_brk),
|
||||
allow_syscall(libc::SYS_chmod),
|
||||
allow_syscall(libc::SYS_clock_adjtime),
|
||||
allow_syscall(libc::SYS_clock_getres),
|
||||
allow_syscall(libc::SYS_clock_gettime),
|
||||
allow_syscall(libc::SYS_clone),
|
||||
allow_syscall(libc::SYS_close),
|
||||
allow_syscall(libc::SYS_connect),
|
||||
allow_syscall(libc::SYS_dup),
|
||||
allow_syscall(libc::SYS_dup2),
|
||||
allow_syscall(libc::SYS_execve),
|
||||
allow_syscall(libc::SYS_exit),
|
||||
allow_syscall(libc::SYS_exit_group),
|
||||
allow_syscall(libc::SYS_fchdir),
|
||||
allow_syscall(libc::SYS_fcntl),
|
||||
allow_syscall(libc::SYS_fork),
|
||||
allow_syscall(libc::SYS_fstat),
|
||||
allow_syscall(libc::SYS_ftruncate),
|
||||
allow_syscall(libc::SYS_futex),
|
||||
allow_syscall(libc::SYS_getcwd),
|
||||
allow_syscall(libc::SYS_getdents),
|
||||
@ -25,6 +30,8 @@ pub fn gen_rules() -> Vec<SyscallRuleSet> {
|
||||
allow_syscall(libc::SYS_geteuid),
|
||||
allow_syscall(libc::SYS_getgid),
|
||||
allow_syscall(libc::SYS_getpid),
|
||||
allow_syscall(libc::SYS_getsockname),
|
||||
allow_syscall(libc::SYS_getsockopt),
|
||||
allow_syscall(libc::SYS_gettid),
|
||||
allow_syscall(libc::SYS_getrandom),
|
||||
allow_syscall(libc::SYS_getrlimit),
|
||||
@ -33,12 +40,16 @@ pub fn gen_rules() -> Vec<SyscallRuleSet> {
|
||||
allow_syscall(libc::SYS_ioctl),
|
||||
allow_syscall(libc::SYS_lseek),
|
||||
allow_syscall(libc::SYS_lstat),
|
||||
allow_syscall(libc::SYS_madvise),
|
||||
// allow_syscall(libc::SYS_mmap),
|
||||
allow_syscall(libc::SYS_mkdir),
|
||||
allow_syscall(libc::SYS_mprotect),
|
||||
// allow_syscall(libc::SYS_munmap),
|
||||
allow_syscall(libc::SYS_nanosleep),
|
||||
allow_syscall(libc::SYS_open),
|
||||
allow_syscall(libc::SYS_openat),
|
||||
allow_syscall(libc::SYS_prctl),
|
||||
allow_syscall(libc::SYS_pread64),
|
||||
allow_syscall(libc::SYS_prlimit64),
|
||||
allow_syscall(libc::SYS_read),
|
||||
allow_syscall(libc::SYS_readlink),
|
||||
@ -46,10 +57,15 @@ pub fn gen_rules() -> Vec<SyscallRuleSet> {
|
||||
allow_syscall(libc::SYS_rt_sigaction),
|
||||
allow_syscall(libc::SYS_rt_sigprocmask),
|
||||
allow_syscall(libc::SYS_rt_sigreturn),
|
||||
allow_syscall(libc::SYS_sched_getaffinity),
|
||||
allow_syscall(libc::SYS_sched_yield),
|
||||
allow_syscall(libc::SYS_select),
|
||||
allow_syscall(libc::SYS_set_robust_list),
|
||||
allow_syscall(libc::SYS_set_tid_address),
|
||||
allow_syscall(libc::SYS_setsockopt),
|
||||
allow_syscall(libc::SYS_sigaltstack),
|
||||
allow_syscall(libc::SYS_socket),
|
||||
allow_syscall(libc::SYS_socketpair),
|
||||
allow_syscall(libc::SYS_stat),
|
||||
allow_syscall(libc::SYS_sysinfo),
|
||||
allow_syscall(libc::SYS_umask),
|
||||
|
||||
@ -44,7 +44,7 @@ pub async fn judger(
|
||||
Some(Language::Node) => "node main.js",
|
||||
Some(Language::TypeScript) => "node main.js",
|
||||
Some(Language::Go) => "./a.out",
|
||||
Some(Language::Java) => "Main.java",
|
||||
Some(Language::Java) => "/usr/bin/java -cp . Main",
|
||||
None => return Err(Error::LanguageNotFound(request.language)),
|
||||
};
|
||||
let process = Process::new(
|
||||
@ -54,9 +54,15 @@ pub async fn judger(
|
||||
data.time_limit,
|
||||
data.memory_limit,
|
||||
)?;
|
||||
debug!("run command: {}", cmd);
|
||||
|
||||
// 开始执行并等待返回结果
|
||||
let runner = process.runner.clone();
|
||||
let mut runner = process.runner.clone();
|
||||
// 为 Java 虚拟机取消内存限制和 trace(万恶的 JVM)
|
||||
if request.language == Language::Java as i32 {
|
||||
runner.memory_limit = -1;
|
||||
runner.traceme = false;
|
||||
}
|
||||
let status = runner.await?;
|
||||
|
||||
resp.set_process_status(&status);
|
||||
@ -126,7 +132,7 @@ pub async fn compile(
|
||||
Some(Language::Node) => "/usr/bin/node /plugins/js/validate.js main.js",
|
||||
Some(Language::TypeScript) => "/usr/bin/tsc main.ts",
|
||||
Some(Language::Go) => "/usr/bin/go build -ldflags \"-s -w\" main.go",
|
||||
Some(Language::Java) => "/usr/bin/java -cp . Main",
|
||||
Some(Language::Java) => "/usr/bin/javac Main.java",
|
||||
None => return Err(Error::LanguageNotFound(request.language)),
|
||||
};
|
||||
debug!("build command: {}", cmd);
|
||||
@ -142,6 +148,10 @@ pub async fn compile(
|
||||
|
||||
let mut runner = process.runner.clone();
|
||||
runner.traceme = false;
|
||||
// 为 Java 虚拟机取消内存限制(万恶的 JVM)
|
||||
if request.language == Language::Java as i32 {
|
||||
runner.memory_limit = -1;
|
||||
}
|
||||
let status = runner.await?;
|
||||
resp.set_process_status(&status);
|
||||
if status.exit_code != 0 || status.signal != 0 {
|
||||
|
||||
160
src/memory.c
Normal file
160
src/memory.c
Normal file
@ -0,0 +1,160 @@
|
||||
#include <ctype.h>
|
||||
#include <linux/limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* in: ' 42964 kB'
|
||||
* out: 42964
|
||||
* */
|
||||
int GetNumByVmLine(char body[])
|
||||
{
|
||||
int offset, ans, start;
|
||||
offset = ans = 0;
|
||||
start = 0; // FALSE on C
|
||||
while (1)
|
||||
{
|
||||
if (!start)
|
||||
{
|
||||
if (isdigit(body[offset]))
|
||||
{
|
||||
start = 1; // TRUE on C
|
||||
}
|
||||
else
|
||||
{
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (start)
|
||||
{
|
||||
if (isdigit(body[offset]))
|
||||
{
|
||||
ans *= 10;
|
||||
ans += (int)(body[offset] - '0');
|
||||
offset++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
long MemoryUsage(int fd)
|
||||
{
|
||||
int i;
|
||||
ssize_t len;
|
||||
char body[4096];
|
||||
long vm_data = 0, vm_stk = 0;
|
||||
|
||||
if ((len = pread(fd, body, 4096, 0)) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
switch (body[i])
|
||||
{
|
||||
case 'V':
|
||||
goto V;
|
||||
default:
|
||||
goto NEXTLINE;
|
||||
}
|
||||
V:
|
||||
i++;
|
||||
switch (body[i])
|
||||
{
|
||||
case 'm':
|
||||
goto Vm;
|
||||
default:
|
||||
goto NEXTLINE;
|
||||
}
|
||||
Vm:
|
||||
i++;
|
||||
switch (body[i])
|
||||
{
|
||||
case 'R':
|
||||
i += 2;
|
||||
goto VmRSS;
|
||||
case 'D':
|
||||
i += 3;
|
||||
goto VmData;
|
||||
case 'S':
|
||||
goto VmS;
|
||||
case 'E':
|
||||
i += 2;
|
||||
goto VmExe;
|
||||
case 'L':
|
||||
goto VmL;
|
||||
default:
|
||||
goto NEXTLINE;
|
||||
}
|
||||
|
||||
VmRSS:
|
||||
i += 2;
|
||||
// vm_rss = GetNumByVmLine(body + i);
|
||||
goto NEXTLINE;
|
||||
|
||||
VmData:
|
||||
i += 2;
|
||||
vm_data = GetNumByVmLine(body + i);
|
||||
goto NEXTLINE;
|
||||
|
||||
VmS:
|
||||
i++;
|
||||
switch (body[i])
|
||||
{
|
||||
case 't':
|
||||
i++;
|
||||
goto VmStk;
|
||||
case 'i':
|
||||
i += 2;
|
||||
goto VmSize;
|
||||
default:
|
||||
goto NEXTLINE;
|
||||
}
|
||||
|
||||
VmStk:
|
||||
i += 2;
|
||||
vm_stk = GetNumByVmLine(body + i);
|
||||
goto NEXTLINE;
|
||||
|
||||
VmSize:
|
||||
i += 2;
|
||||
// vm_size = GetNumByVmLine(body + i);
|
||||
goto NEXTLINE;
|
||||
|
||||
VmExe:
|
||||
i += 2;
|
||||
// vm_exe = GetNumByVmLine(body + i);
|
||||
goto NEXTLINE;
|
||||
|
||||
VmL:
|
||||
i++;
|
||||
switch (body[i])
|
||||
{
|
||||
case 'i':
|
||||
i++;
|
||||
goto VmLib;
|
||||
}
|
||||
|
||||
VmLib:
|
||||
i += 2;
|
||||
// vm_lib = GetNumByVmLine(body + i);
|
||||
goto NEXTLINE;
|
||||
|
||||
NEXTLINE:
|
||||
while (body[i] != '\n')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return vm_data + vm_stk;
|
||||
}
|
||||
@ -8,7 +8,7 @@ pub fn standard_result(out: &[u8], ans: &[u8]) -> Result<JudgeResult> {
|
||||
let mut ans_offset = 0;
|
||||
// 没有 PE,PE 直接 WA
|
||||
let mut r = JudgeResult::Accepted;
|
||||
while out_offset < out_len && ans_offset < ans_len {
|
||||
while out_offset <= out_len && ans_offset <= ans_len {
|
||||
let (out_start, out_end, out_exists) = next_line(&out, out_offset, out_len);
|
||||
let (ans_start, ans_end, ans_exists) = next_line(&ans, ans_offset, ans_len);
|
||||
if !out_exists || !ans_exists {
|
||||
@ -159,4 +159,25 @@ mod tests {
|
||||
let out: &[u8] = "Hello World!\t\t\t\t\n\n\n\n \n\n\n\n\t\t\t\t".as_bytes();
|
||||
assert_eq!(standard_result(out, ans).unwrap(), JudgeResult::Accepted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test8() {
|
||||
let ans: &[u8] = "Hello World!".as_bytes();
|
||||
let out: &[u8] = "".as_bytes();
|
||||
assert_eq!(standard_result(out, ans).unwrap(), JudgeResult::WrongAnswer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test9() {
|
||||
let ans: &[u8] = "".as_bytes();
|
||||
let out: &[u8] = "".as_bytes();
|
||||
assert_eq!(standard_result(out, ans).unwrap(), JudgeResult::Accepted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test10() {
|
||||
let ans: &[u8] = "Hello World!".as_bytes();
|
||||
let out: &[u8] = "Hello World!\n".as_bytes();
|
||||
assert_eq!(standard_result(out, ans).unwrap(), JudgeResult::Accepted);
|
||||
}
|
||||
}
|
||||
|
||||
138
src/runner.rs
138
src/runner.rs
@ -1,23 +1,30 @@
|
||||
extern crate nix;
|
||||
|
||||
use super::allow::{gen_rules, trace_syscall};
|
||||
use super::config::{STDERR_FILENAME, STDIN_FILENAME, STDOUT_FILENAME};
|
||||
use super::error::{errno_str, Error, Result};
|
||||
use super::exec_args::ExecArgs;
|
||||
use super::seccomp::*;
|
||||
use nix::unistd::close;
|
||||
use std::convert::TryInto;
|
||||
use std::env;
|
||||
use std::ffi::CString;
|
||||
use std::fs::File;
|
||||
use std::fs::{remove_file, File};
|
||||
use std::future::Future;
|
||||
use std::io::{self, prelude::*, BufReader};
|
||||
use std::path::PathBuf;
|
||||
use std::io;
|
||||
use std::os::unix::io::IntoRawFd;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::pin::Pin;
|
||||
use std::ptr;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{mpsc, Arc, Mutex};
|
||||
use std::task::{Context, Poll};
|
||||
use std::thread;
|
||||
use std::time::SystemTime;
|
||||
|
||||
extern "C" {
|
||||
fn MemoryUsage(fd: i32) -> i64;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Runner {
|
||||
pub pid: i32,
|
||||
@ -161,12 +168,18 @@ impl Runner {
|
||||
unsafe {
|
||||
// 重定向文件描述符
|
||||
dup(STDIN_FILENAME, libc::STDIN_FILENO, libc::O_RDONLY, 0o644);
|
||||
if Path::new(STDOUT_FILENAME).exists() {
|
||||
remove_file(STDOUT_FILENAME).unwrap();
|
||||
}
|
||||
dup(
|
||||
STDOUT_FILENAME,
|
||||
libc::STDOUT_FILENO,
|
||||
libc::O_CREAT | libc::O_RDWR,
|
||||
0o644,
|
||||
);
|
||||
if Path::new(STDERR_FILENAME).exists() {
|
||||
remove_file(STDERR_FILENAME).unwrap();
|
||||
}
|
||||
dup(
|
||||
STDERR_FILENAME,
|
||||
libc::STDERR_FILENO,
|
||||
@ -180,7 +193,7 @@ impl Runner {
|
||||
panic!("How dare you!");
|
||||
}
|
||||
// CPU 时间限制,粒度为 S
|
||||
rl.rlim_cur = (self.time_limit / 1000 + 1) as u64;
|
||||
rl.rlim_cur = (self.time_limit as u64) / 1000 + 1;
|
||||
rl.rlim_max = rl.rlim_cur + 1;
|
||||
if libc::setrlimit(libc::RLIMIT_CPU, &rl) != 0 {
|
||||
eprintln!("setrlimit failure!");
|
||||
@ -188,17 +201,19 @@ impl Runner {
|
||||
panic!("How dare you!");
|
||||
}
|
||||
// 设置内存限制
|
||||
rl.rlim_cur = (self.memory_limit * 1024) as u64;
|
||||
rl.rlim_max = rl.rlim_cur + 1024;
|
||||
if libc::setrlimit(libc::RLIMIT_DATA, &rl) != 0 {
|
||||
eprintln!("setrlimit failure!");
|
||||
eprintln!("{:?}", io::Error::last_os_error().raw_os_error());
|
||||
panic!("How dare you!");
|
||||
}
|
||||
if libc::setrlimit(libc::RLIMIT_AS, &rl) != 0 {
|
||||
eprintln!("setrlimit failure!");
|
||||
eprintln!("{:?}", io::Error::last_os_error().raw_os_error());
|
||||
panic!("How dare you!");
|
||||
if self.memory_limit > 0 {
|
||||
rl.rlim_cur = (self.memory_limit as u64) * 1024;
|
||||
rl.rlim_max = rl.rlim_cur + 1024;
|
||||
if libc::setrlimit(libc::RLIMIT_DATA, &rl) != 0 {
|
||||
eprintln!("setrlimit failure!");
|
||||
eprintln!("{:?}", io::Error::last_os_error().raw_os_error());
|
||||
panic!("How dare you!");
|
||||
}
|
||||
if libc::setrlimit(libc::RLIMIT_AS, &rl) != 0 {
|
||||
eprintln!("setrlimit failure!");
|
||||
eprintln!("{:?}", io::Error::last_os_error().raw_os_error());
|
||||
panic!("How dare you!");
|
||||
}
|
||||
}
|
||||
if self.traceme {
|
||||
// 设置 trace 模式
|
||||
@ -229,6 +244,7 @@ impl Runner {
|
||||
}
|
||||
SeccompFilter::apply(filter.try_into().unwrap()).unwrap();
|
||||
libc::execve(exec_args.pathname, exec_args.argv, exec_args.envp);
|
||||
libc::kill(libc::getpid(), libc::SIGKILL);
|
||||
}
|
||||
panic!("How dare you!");
|
||||
}
|
||||
@ -267,6 +283,17 @@ impl Runner {
|
||||
// from: https://www.hackerearth.com/practice/notes/vivekprakash/technical-diving-into-memory-used-by-a-program-in-online-judges/
|
||||
// VmRSS 为程序当前驻留在物理内存中的大小,对虚拟内存等无效
|
||||
let mut vm_mem = 0;
|
||||
let status_file = format!("/proc/{}/status", pid);
|
||||
let file = match File::open(status_file) {
|
||||
Ok(val) => val,
|
||||
Err(_) => {
|
||||
return judge_error(format!(
|
||||
"open file `{}` failure!",
|
||||
format!("/proc/{}/status", pid)
|
||||
))
|
||||
}
|
||||
};
|
||||
let status_fd = file.into_raw_fd();
|
||||
|
||||
unsafe {
|
||||
if self.traceme {
|
||||
@ -283,52 +310,15 @@ impl Runner {
|
||||
libc::ptrace(libc::PTRACE_SYSCALL, pid, 0, 0);
|
||||
libc::waitpid(pid, &mut status, 0);
|
||||
|
||||
// 通过 /proc/pid/status 读取内存占用
|
||||
let status_file = format!("/proc/{}/status", pid);
|
||||
debug!("{}", status_file);
|
||||
let file = match File::open(status_file) {
|
||||
Ok(val) => val,
|
||||
Err(_) => {
|
||||
return judge_error(format!(
|
||||
"open file `{}` failure!",
|
||||
format!("/proc/{}/status", pid)
|
||||
))
|
||||
}
|
||||
};
|
||||
let reader = BufReader::new(file);
|
||||
let mut vm_data = 0;
|
||||
let mut vm_stk = 0;
|
||||
for line in reader.lines() {
|
||||
let s = match line {
|
||||
Ok(val) => val,
|
||||
Err(_) => return judge_error("readline failure!".to_string()),
|
||||
};
|
||||
if s.starts_with("VmData") {
|
||||
let len = s.len() - 2;
|
||||
let mem = &s[7..len].trim();
|
||||
let mem = match mem.parse::<i64>() {
|
||||
Ok(val) => val,
|
||||
Err(_) => return judge_error(format!("parse {} failure!", mem)),
|
||||
};
|
||||
if vm_data < mem {
|
||||
vm_data = mem;
|
||||
}
|
||||
debug!("vm_data: {}", vm_data);
|
||||
} else if s.starts_with("VmStk") {
|
||||
let len = s.len() - 2;
|
||||
let mem = &s[6..len].trim();
|
||||
let mem = match mem.parse::<i64>() {
|
||||
Ok(val) => val,
|
||||
Err(_) => return judge_error(format!("parse {} failure!", mem)),
|
||||
};
|
||||
if vm_stk < mem {
|
||||
vm_stk = mem;
|
||||
}
|
||||
debug!("vm_stk: {}", vm_stk);
|
||||
}
|
||||
let vmem = MemoryUsage(status_fd);
|
||||
if vm_mem < vmem {
|
||||
vm_mem = vmem;
|
||||
}
|
||||
if vm_mem < vm_stk + vm_data {
|
||||
vm_mem = vm_stk + vm_data;
|
||||
// trace 模式下,如果检测到内存已经超出限制,则直接 kill & break
|
||||
if vm_mem > self.memory_limit.into() {
|
||||
debug!("MemoryLimitExceeded! break");
|
||||
libc::kill(pid, libc::SIGKILL);
|
||||
break;
|
||||
}
|
||||
debug!("vm_mem: {}", vm_mem);
|
||||
|
||||
@ -341,23 +331,25 @@ impl Runner {
|
||||
debug!("exited: {}", libc::WIFEXITED(status));
|
||||
break;
|
||||
}
|
||||
debug!("exited: {}", libc::WIFEXITED(status));
|
||||
// debug!("exited: {}", libc::WIFEXITED(status));
|
||||
}
|
||||
}
|
||||
|
||||
match close(status_fd) {
|
||||
Ok(_) => {}
|
||||
Err(_) => return judge_error("close status file failure!".to_string()),
|
||||
};
|
||||
let mut exit_code = 0;
|
||||
let exited = unsafe { libc::WIFEXITED(status) };
|
||||
let exited = libc::WIFEXITED(status);
|
||||
if exited {
|
||||
exit_code = unsafe { libc::WEXITSTATUS(status) };
|
||||
exit_code = libc::WEXITSTATUS(status);
|
||||
}
|
||||
let signal = unsafe {
|
||||
if libc::WIFSIGNALED(status) {
|
||||
libc::WTERMSIG(status)
|
||||
} else if libc::WIFSTOPPED(status) {
|
||||
libc::WSTOPSIG(status)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
let signal = if libc::WIFSIGNALED(status) {
|
||||
libc::WTERMSIG(status)
|
||||
} else if libc::WIFSTOPPED(status) {
|
||||
libc::WSTOPSIG(status)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
// TODO: 添加 CGroup 的量度
|
||||
let time_used = rusage.ru_utime.tv_sec * 1000
|
||||
|
||||
Loading…
Reference in New Issue
Block a user