From cd13ec33434d9a51568be1724a0c53803e1fdfbb Mon Sep 17 00:00:00 2001 From: Artin Date: Sun, 28 Feb 2021 11:46:40 +0800 Subject: [PATCH] feat: add memory_check_only close: add config memory_limit_check_only #8 --- Makefile | 2 +- README.md | 10 +++++----- src/judge.c | 10 ++++++---- src/run.c | 27 +++++++++++++++++---------- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 1d49d88..1c2114c 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ testc: c judge NODE_BASE=./tests/node testnode: judge - ./judge -l node.log -t 1000 -i $(NODE_BASE)/1.in -o $(NODE_BASE)/1.out -u node.tmp.out -- node $(NODE_BASE)/main.js + ./judge -l node.log -t 1000 -m 2048 --mco -i $(NODE_BASE)/1.in -o $(NODE_BASE)/1.out -u node.tmp.out -- node $(NODE_BASE)/main.js cleantest: diff --git a/README.md b/README.md index 2b28cea..88b84bd 100644 --- a/README.md +++ b/README.md @@ -37,26 +37,26 @@ make libjudge 下面简单介绍一个例子: -![example](https://user-images.githubusercontent.com/13938334/109389825-1b264b00-7949-11eb-9b07-11778ba3c77b.png) +![image](https://user-images.githubusercontent.com/13938334/109407241-1baafa00-79ba-11eb-8f14-51fa0ee23d27.png) 判本仓库根目录下 `tests/node/` 的题。 只需要执行 `./judge [选项...] <命令> [参数...]` 即可,比如: ```sh -./judge -l node.log -t 1000 -i ./tests/node/1.in -o ./tests/node/1.out -u node.tmp.out node ./tests/node/main.js +./judge -l node.log -t 1000 -m 2048 --mco -i ./tests/node/1.in -o ./tests/node/1.out -u node.tmp.out -- node ./tests/node/main.js ``` 各参数意义: - `-l, --log_file` Log 日志路径 -- `-t, --cpu_time_limit` 限制 CPU 时间,单位是 ms +- `-t, --cpu_time_limit` CPU 时间限制 ,单位是 ms,用于判断是否超过 CPU 时间限制。 +- `-m, --memory_limit` 内存限制,单位是 kb,用于判断是否超过内存限制。 +- `--memory_check_only, --mco` 只进行内存限制的检查(要确认判题结果),而不进行真正的内存限制,因为在执行 Node.js 时,限制内存会导致 `node` 程序无法正常执行,会报段错误。 - `-i, --system_input` 从该文件读入数据当成待判程序的标准输入,如果不设置,也可以直接向程序使用 pipe 的方式输入数据。 - `-o, --system_output` 判题数据的输出,用于比对程序是否运行正确。 - `-u, --user_output` 将待判程序的标准输出写入该文件。 -这里没有用到 `-m` 限制 Memory 的使用,因为在执行 Node.js 时,限制内存会导致 `node` 程序无法正常执行。 - 更多选项可以输入 `./judge -?` 查看帮助。 如果执行待判程序的命令的参数中需要使用到 `-`(如想用判题程序执行: `python --version`),那你需要将这个参数放在 `--` 后,如: diff --git a/src/judge.c b/src/judge.c index 6f7fd57..d09e8b7 100644 --- a/src/judge.c +++ b/src/judge.c @@ -64,7 +64,7 @@ void log_config(struct Config *config) log_debug("config: cpu_time_limit %d ms", config->cpu_time_limit); log_debug("config: real_time_limit %d ms", config->real_time_limit); log_debug("config: memory_limit %d kb", config->memory_limit); - log_debug("config: memory_check_only %d kb", config->memory_check_only); + log_debug("config: memory_check_only %d", config->memory_check_only); log_debug("config: in_file %s", config->in_file); log_debug("config: out_file %s", config->out_file); log_debug("config: user_out_file %s", config->user_out_file); @@ -113,10 +113,12 @@ int main(int argc, char *argv[]) CLOSE_LOGGER_FILE(); exit(EXIT_FAILURE); } - - if (config.judge_mode == 1) + if (result.status == PENDING || result.status == ACCEPTED) { - diff(&config, &result.status); + if (config.judge_mode == 1) + { + diff(&config, &result.status); + } } print_result(&result); } diff --git a/src/run.c b/src/run.c index 3f25389..7c1d084 100644 --- a/src/run.c +++ b/src/run.c @@ -40,15 +40,18 @@ void child_process(struct Config *_config) // 注意,设置 memory_limit 会导致有些程序 crash,比如 python, node if (_config->memory_limit != RESOURCE_UNLIMITED) { - // The maximum size of the process's virtual memory (address space) in bytes. - log_debug("set memory_limit"); - - struct rlimit max_memory_rl; - // 为了避免代码是正确的,但是因为超过内存 oom 而被判定为 re。 - // 如果程序占用低于两倍,最后再重新检查内存占用和配置的关系,就可以判定为超内存而不是 re,如果超过两倍,那就真的 re 了(可能会被 kill)。 - max_memory_rl.rlim_max = max_memory_rl.rlim_cur = _config->memory_limit * 1024 * 2; - if (setrlimit(RLIMIT_AS, &max_memory_rl)) - CHILD_ERROR_EXIT("set RLIMIT_AS failure"); + if (_config->memory_check_only == 0) + { + // The maximum size of the process's virtual memory (address space) in bytes. + log_debug("set memory_limit"); + + struct rlimit max_memory_rl; + // 为了避免代码是正确的,但是因为超过内存 oom 而被判定为 re。 + // 如果程序占用低于两倍,最后再重新检查内存占用和配置的关系,就可以判定为超内存而不是 re,如果超过两倍,那就真的 re 了(可能会被 kill)。 + max_memory_rl.rlim_max = max_memory_rl.rlim_cur = _config->memory_limit * 1024 * 2; + if (setrlimit(RLIMIT_AS, &max_memory_rl)) + CHILD_ERROR_EXIT("set RLIMIT_AS failure"); + } } log_debug("set max_output_size"); @@ -184,9 +187,9 @@ void monitor(pid_t child_pid, struct Config *_config, struct Result *_result, st } else { - log_debug("child process exit normal"); // 程序正常结束,此时可通过WEXITSTATUS(status)获取进程退出状态(exit时参数) _result->exit_code = WEXITSTATUS(status); + log_debug("child process exit_code %d", _result->exit_code); if (_result->exit_code != 0) { @@ -195,9 +198,13 @@ void monitor(pid_t child_pid, struct Config *_config, struct Result *_result, st else { if (_result->cpu_time_used > _config->cpu_time_limit) + { _result->status = TIME_LIMIT_EXCEEDED; + } else if (_result->memory_used > _config->memory_limit) + { _result->status = MEMORY_LIMIT_EXCEEDED; + } } } }