void set_compile_limit() { if (oj_solution.lang == LANG_JAVA || oj_solution.lang == LANG_PYTHON27 || oj_solution.lang == LANG_PYTHON3 || oj_solution.lang == LANG_KOTLIN) return; rlimit lim{}; lim.rlim_cur = lim.rlim_max = compile_time_limit / 1000; if (setrlimit(RLIMIT_CPU, &lim) < 0) { FM_LOG_FATAL("setrlimit RLIMIT_CPU failed: %s", strerror(errno)); exit(EXIT_SET_LIMIT); } if (EXIT_SUCCESS != malarm(ITIMER_REAL, compile_time_limit)) { FM_LOG_FATAL("malarm for compiler failed: %s", strerror(errno)); exit(EXIT_SET_LIMIT); } lim.rlim_cur = lim.rlim_max = compile_memory_limit * STD_MB; if (setrlimit(RLIMIT_AS, &lim) < 0) { FM_LOG_FATAL("setrlimit RLIMIT_AS failed: %s", strerror(errno)); exit(EXIT_SET_LIMIT); } lim.rlim_cur = lim.rlim_max = compile_fsize_limit * STD_MB; if (setrlimit(RLIMIT_FSIZE, &lim) < 0) { FM_LOG_FATAL("setrlimit RLIMIT_FSIZE failed: %s", strerror(errno)); exit(EXIT_SET_LIMIT); } FM_LOG_DEBUG("set compile limit ok"); }
int main(int argc, char *argv[]) { log_open("./core_log.txt"); //或许写成参数更好,懒得写了 atexit(output_result); //退出程序时的回调函数,用于输出判题结果 //为了构建沙盒,必须要有root权限 if (geteuid() != 0) { FM_LOG_FATAL("You must run this program as root."); exit(JUDGE_CONF::EXIT_UNPRIVILEGED); } parse_arguments(argc, argv); JUDGE_CONF::JUDGE_TIME_LIMIT += PROBLEM::time_limit; if (EXIT_SUCCESS != malarm(ITIMER_REAL, JUDGE_CONF::JUDGE_TIME_LIMIT)) { FM_LOG_WARNING("Set the alarm for this judge program failed, %d: %s", errno, strerror(errno)); exit(JUDGE_CONF::EXIT_VERY_FIRST); } signal(SIGALRM, timeout); compiler_source_code(); judge(); if (PROBLEM::spj) { run_spj(); } else { if (PROBLEM::result == JUDGE_CONF::SE) PROBLEM::result = compare_output(PROBLEM::output_file, PROBLEM::exec_output); } return 0; }
// Run spj int oj_compare_output_spj(const char *file_in, // std input file const char *file_out, // std output file const char *file_user, // user output file const char *spj_exec) // path of spj { FM_LOG_TRACE("start compare spj"); pid_t pid_spj = fork(); // create a child process for spj if (pid_spj < 0) { FM_LOG_FATAL("fork for spj failed: %s", strerror(errno)); exit(EXIT_COMPARE_SPJ); } else if (pid_spj == 0) { // child process log_add_info("spj"); // Set spj timeout if (EXIT_SUCCESS == malarm(ITIMER_REAL, spj_time_limit)) { FM_LOG_TRACE("load spj: %s", spj_exec); execlp(spj_exec, spj_exec, file_in, file_out, file_user, NULL); FM_LOG_FATAL("execute spj failed"); exit(EXIT_COMPARE_SPJ_FORK); } else { FM_LOG_FATAL("malarm for spj failed: %s", strerror(errno)); exit(EXIT_COMPARE_SPJ); } } else { int status = 0; if (waitpid(pid_spj, &status, 0) < 0) { FM_LOG_FATAL("waitpid for spj failed: %s", strerror(errno)); exit(EXIT_COMPARE_SPJ); } if (WIFEXITED(status)) { switch (WEXITSTATUS(status)) { case SPJ_AC: return OJ_AC; case SPJ_PE: return OJ_PE; case SPJ_WA: return OJ_WA; default: return OJ_VE; } } else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGALRM) { // recv SIGNALRM FM_LOG_WARNING("spj: time out"); } else { // spj RE FM_LOG_WARNING("unkown termination, status = %d", status); } } return OJ_VE; }
int main(int argc, char *argv[], char *envp[]) { if (nice(10) == -1) { // increase nice value(decrease pripority) FM_LOG_WARNING("increase nice value failed: %s", strerror(errno)); } init(); parse_arguments(argc, argv); if (geteuid() == 0) { // effective user is not root FM_LOG_FATAL("please do not run as root, run as judge"); exit(EXIT_PRIVILEGED); } if (EXIT_SUCCESS != chdir(oj_solution.work_dir)) { // change current directory FM_LOG_FATAL("chdir(%s) failed: %s", oj_solution.work_dir, strerror(errno)); exit(EXIT_CHDIR); } FM_LOG_DEBUG("\n\x1b[31m----- Power Judge 1.0 -----\x1b[0m"); judge_time_limit += oj_solution.time_limit; judge_time_limit *= get_num_of_test(); if (EXIT_SUCCESS != malarm(ITIMER_REAL, judge_time_limit)) { FM_LOG_FATAL("set alarm for judge failed: %s", strerror(errno)); exit(EXIT_VERY_FIRST); } if (signal(SIGALRM, timeout_hander) == SIG_ERR) { // install signal hander for timeout FM_LOG_FATAL("cannot handle SIGALRM"); exit(EXIT_VERY_FIRST); } init_connet(); compile(); run_solution(); close_connet(); return 0; }
bool judge(const char *input_file, const char *output_file_std, const char *stdout_file_executive, const char *stderr_file_executive) { rusage rused{}; pid_t executor = fork(); // create a child process for executor if (executor < 0) { FM_LOG_FATAL("fork executor failed: %s", strerror(errno)); exit(EXIT_PRE_JUDGE); } else if (executor == 0) { // child process log_add_info("executor"); off_t fsize = file_size(output_file_std); // io redirect, must before set_security_option() io_redirect(input_file, stdout_file_executive, stderr_file_executive); // chroot & setuid set_security_option(); // set memory, time and file size limit etc. set_limit(fsize); // must after set_security_option() FM_LOG_DEBUG("time limit: %d, time limit addtion: %d", oj_solution.time_limit, time_limit_addtion); uint64_t real_time_limit = oj_solution.time_limit + time_limit_addtion; // time fix // set real time alarm if (EXIT_SUCCESS != malarm(ITIMER_REAL, real_time_limit)) { FM_LOG_FATAL("malarm for executor failed: %s", strerror(errno)); exit(EXIT_PRE_JUDGE); } FM_LOG_TRACE("begin execute"); if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) { FM_LOG_FATAL("Trace executor failed: %s", strerror(errno)); exit(EXIT_PRE_JUDGE_PTRACE); } // load program if (oj_solution.lang == LANG_JAVA) { print_executor(EXEC_J); execvp(EXEC_J[0], (char *const *) EXEC_J); } else if (oj_solution.lang == LANG_KOTLIN) { print_executor(EXEC_KT); execvp(EXEC_KT[0], (char *const *) EXEC_KT); } else if (oj_solution.lang == LANG_PYTHON27) { print_executor(EXEC_PY27); #ifdef FAST_JUDGE execvp(EXEC_PY27[0], (char * const *) EXEC_PY27); #else execv(EXEC_PY27[0], (char *const *) EXEC_PY27); #endif } else if (oj_solution.lang == LANG_PYTHON3) { print_executor(EXEC_PY3); #ifdef FAST_JUDGE execvp(EXEC_PY3[0], (char * const *) EXEC_PY3); #else execv(EXEC_PY3[0], (char *const *) EXEC_PY3); #endif } else { execl("./Main", "./Main", NULL); } // exec error FM_LOG_FATAL("exec error"); exit(EXIT_PRE_JUDGE_EXECLP); } else { // Judger int status = 0; user_regs_struct regs{}; stderr = freopen("error.txt", "a+", stderr); init_syscalls(oj_solution.lang); while (true) { if (wait4(executor, &status, 0, &rused) < 0) { FM_LOG_FATAL("wait4 executor failed: %s", strerror(errno)); kill(executor, SIGKILL); exit(EXIT_JUDGE); } if (WIFEXITED(status)) { if ((oj_solution.lang != LANG_JAVA && oj_solution.lang != LANG_KOTLIN) || WEXITSTATUS(status) == EXIT_SUCCESS) { // AC PE WA FM_LOG_TRACE("normal quit"); int result; if (oj_solution.spj) { // use SPJ result = oj_compare_output_spj(input_file, output_file_std, stdout_file_executive, oj_solution.spj_exe_file); } else { // compare file result = oj_compare_output(output_file_std, stdout_file_executive); } // WA if (result == OJ_WA) { oj_solution.result = OJ_WA; } else if (oj_solution.result != OJ_PE) { // previous case is AC oj_solution.result = result; // AC or PE } else /* (oj_solution.result == OJ_PE) */ { // previous case is PE oj_solution.result = OJ_PE; } FM_LOG_NOTICE("case result: %d, problem result: %d", result, oj_solution.result); } else { // not return 0 oj_solution.result = OJ_RE; FM_LOG_NOTICE("abnormal quit, exit_code: %d", WEXITSTATUS(status)); } break; } // RE/TLE/OLE if (WIFSIGNALED(status) || (WIFSTOPPED(status) && WSTOPSIG(status) != SIGTRAP)) { int signo = 0; if (WIFSIGNALED(status)) { signo = WTERMSIG(status); FM_LOG_NOTICE("child process killed by signal %d, %s", signo, strsignal(signo)); } else { signo = WSTOPSIG(status); FM_LOG_NOTICE("child process stopped by signal %d, %s", signo, strsignal(signo)); } switch (signo) { // Ignore case SIGCHLD: oj_solution.result = OJ_AC; break; // TLE case SIGALRM: // alarm() and setitimer(ITIMER_REAL) case SIGVTALRM: // setitimer(ITIMER_VIRTUAL) case SIGXCPU: // exceeds soft processor limit oj_solution.result = OJ_TLE; FM_LOG_TRACE("Time Limit Exceeded: %s", strsignal(signo)); break; // OLE case SIGXFSZ: // exceeds file size limit oj_solution.result = OJ_OLE; FM_LOG_TRACE("Output Limit Exceeded"); break; // RE case SIGSEGV: // segmentation violation case SIGFPE: // any arithmetic exception case SIGBUS: // the process incurs a hardware fault case SIGABRT: // abort() function case SIGKILL: // exceeds hard processor limit default: oj_solution.result = OJ_RE; FILE *fp = fopen(stderr_file_executive, "a+"); if (fp == nullptr) { fprintf(stderr, "%s\n", strsignal(signo)); FM_LOG_WARNING("Runtime Error: %s", strsignal(signo)); } else { fprintf(fp, "%s\n", strsignal(signo)); fclose(fp); } break; } // end of swtich kill(executor, SIGKILL); break; } // end of "if (WIFSIGNALED(status) ...)" oj_solution.memory_usage = std::max(oj_solution.memory_usage, (unsigned long) rused.ru_maxrss); // TODO(power): check why memory exceed too much if (oj_solution.memory_usage > oj_solution.memory_limit) { oj_solution.result = OJ_MLE; kill(executor, SIGKILL); break; } // check syscall if (ptrace(PTRACE_GETREGS, executor, NULL, ®s) < 0) { FM_LOG_FATAL("ptrace(PTRACE_GETREGS) failed: %s", strerror(errno)); kill(executor, SIGKILL); exit(EXIT_JUDGE); } int syscall_id = 0; #ifdef __i386__ syscall_id = (int)regs.orig_eax; #else syscall_id = (int) regs.orig_rax; #endif if (syscall_id > 0 && !is_valid_syscall(syscall_id)) { oj_solution.result = OJ_RF; FM_LOG_FATAL("restricted function, syscall_id: %d", syscall_id); kill(executor, SIGKILL); break; } if (ptrace(PTRACE_SYSCALL, executor, NULL, NULL) < 0) { FM_LOG_FATAL("ptrace(PTRACE_SYSCALL) failed: %s", strerror(errno)); kill(executor, SIGKILL); exit(EXIT_JUDGE); } } // end of while } // end of fork for judge process oj_solution.memory_usage = std::max(oj_solution.memory_usage, (unsigned long) rused.ru_maxrss); if (oj_solution.memory_usage > oj_solution.memory_limit) { oj_solution.result = OJ_MLE; FM_LOG_NOTICE("memory limit exceeded: %d (fault: %d * %d)", oj_solution.memory_usage, rused.ru_minflt, page_size); } oj_solution.time_usage = std::max(oj_solution.time_usage, (unsigned long) rused.ru_utime.tv_sec * 1000 + rused.ru_utime.tv_usec / 1000); if (oj_solution.time_usage > oj_solution.time_limit) { oj_solution.result = OJ_TLE; FM_LOG_TRACE("Time Limit Exceeded"); } if (oj_solution.result != OJ_AC) { if (oj_solution.judge_type == ACM) { FM_LOG_NOTICE("not AC/PE, no need to continue"); } if (oj_solution.result == OJ_TLE) { oj_solution.time_usage = oj_solution.time_limit; } else if (oj_solution.result == OJ_WA) { if (oj_solution.lang == LANG_JAVA) { // TODO: kotlin fix_java_result(stdout_file_executive, stderr_file_executive); } else if ((oj_solution.lang == LANG_PYTHON27 || oj_solution.lang == LANG_PYTHON3) && file_size(stderr_file_executive)) { oj_solution.result = OJ_RE; FM_LOG_TRACE("Runtime Error"); } } return false; } return true; }
static void run_spj() { // support ljudge style special judge const char origin_name[3][16] = {"./in.in", "./out.out", "./out.txt"}; const char target_name[4][16] = {"/input", "/output", "/user_output", "/user_code"}; for (int i = 0; i < 4; i++) { std::string origin_path = (i != 3) ? origin_name[i] : PROBLEM::code_path; std::string target_path = PROBLEM::run_dir + target_name[i]; if (EXIT_SUCCESS != symlink(origin_path.c_str(), target_path.c_str())) FM_LOG_WARNING("Create symbolic link from '%s' to '%s' failed,%d:%s.", origin_path.c_str(), target_path.c_str(), errno, strerror(errno)); } pid_t spj_pid = fork(); int status = 0; if (spj_pid < 0) { FM_LOG_WARNING("fork for special judge failed.So sad."); exit(JUDGE_CONF::EXIT_COMPARE_SPJ); } else if (spj_pid == 0) { FM_LOG_TRACE("Woo, I will start special judge!"); stdin = freopen(PROBLEM::input_file.c_str(), "r", stdin); // ljudge style stdout = freopen(PROBLEM::spj_output_file.c_str(), "w", stdout); if (stdin == NULL || stdout == NULL) { FM_LOG_WARNING("redirect io in spj failed."); exit(JUDGE_CONF::EXIT_COMPARE_SPJ); } //SPJ时间限制 if (EXIT_SUCCESS != malarm(ITIMER_REAL, JUDGE_CONF::SPJ_TIME_LIMIT)) { FM_LOG_WARNING("Set time limit for spj failed."); exit(JUDGE_CONF::EXIT_COMPARE_SPJ); } security_control_spj(); if (PROBLEM::spj_lang != JUDGE_CONF::LANG_JAVA) { execl("./SpecialJudge", "SpecialJudge", "user_output", NULL); } else { execlp("java", "java", "SpecialJudge", NULL); } exit(JUDGE_CONF::EXIT_COMPARE_SPJ_FORK); } else { if (wait4(spj_pid, &status, 0, NULL) < 0) { FM_LOG_WARNING("wait4 failed."); exit(JUDGE_CONF::EXIT_COMPARE_SPJ); } if (WIFEXITED(status)) { int spj_exit_code = WEXITSTATUS(status); if (spj_exit_code >= 0 && spj_exit_code < 4) { FM_LOG_TRACE("Well, SpecialJudge program normally quit.All is good."); // 获取SPJ结果 switch (spj_exit_code) { case 0: PROBLEM::result = JUDGE_CONF::AC; break; case 1: PROBLEM::result = JUDGE_CONF::WA; break; case 2: PROBLEM::result = JUDGE_CONF::PE; break; } return ; } else { FM_LOG_WARNING("I am sorry to tell you that the special judge program abnormally terminated. %d", WEXITSTATUS(status)); } } else if (WIFSIGNALED(status) && WTERMSIG(status) == SIGALRM) { FM_LOG_WARNING("Well, the special judge program consume too much time."); } else { FM_LOG_WARNING("Actually, I do not kwon why the special judge program dead."); } } }
/* * 执行用户提交的程序 */ static void judge() { struct rusage rused; pid_t executive = fork(); if (executive < 0) { exit(JUDGE_CONF::EXIT_PRE_JUDGE); } else if (executive == 0) { //子进程,用户程序 FM_LOG_TRACE("Start Judging."); io_redirect(); security_control(); int real_time_limit = PROBLEM::time_limit; if (EXIT_SUCCESS != malarm(ITIMER_REAL, real_time_limit)) { exit(JUDGE_CONF::EXIT_PRE_JUDGE); } set_limit(); if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) { exit(JUDGE_CONF::EXIT_PRE_JUDGE_PTRACE); } if (PROBLEM::lang != JUDGE_CONF::LANG_JAVA){ execl("./a.out", "a.out", NULL); } else { execlp("java", "java", "Main", NULL); } //走到这了说明出错了 exit(JUDGE_CONF::EXIT_PRE_JUDGE_EXECLP); } else { //父进程 int status = 0; //子进程状态 int syscall_id = 0; //系统调用号 struct user_regs_struct regs; //寄存器 init_RF_table(PROBLEM::lang); //初始化系统调用表 while (true) {//循环监控子进程 if (wait4(executive, &status, 0, &rused) < 0) { FM_LOG_WARNING("wait4 failed."); exit(JUDGE_CONF::EXIT_JUDGE); } //自行退出 if (WIFEXITED(status)) { if (PROBLEM::lang != JUDGE_CONF::LANG_JAVA || WEXITSTATUS(status) == EXIT_SUCCESS) { FM_LOG_TRACE("OK, normal quit. All is good."); //PROBLEM::result = JUDGE_CONF::PROCEED; } else { FM_LOG_WARNING("oh, some error occured.Abnormal quit."); PROBLEM::result = JUDGE_CONF::RE; } break; } //被信号终止掉了 if (WIFSIGNALED(status) || (WIFSTOPPED(status) && WSTOPSIG(status) != SIGTRAP)) { //要过滤掉SIGTRAP信号 int signo = 0; if (WIFSIGNALED(status)) { signo = WTERMSIG(status); FM_LOG_WARNING("child signaled by %d : %s", signo, strsignal(signo)); } else { signo = WSTOPSIG(status); FM_LOG_WARNING("child stop by %d : %s\n", signo, strsignal(signo)); } switch (signo) { //TLE case SIGALRM: case SIGXCPU: case SIGVTALRM: case SIGKILL: FM_LOG_TRACE("Well, Time Limit Exeeded"); PROBLEM::time_usage = 0; PROBLEM::memory_usage = 0; PROBLEM::result = JUDGE_CONF::TLE; break; case SIGXFSZ: FM_LOG_TRACE("File Limit Exceeded"); PROBLEM::time_usage = 0; PROBLEM::memory_usage = 0; PROBLEM::result = JUDGE_CONF::OLE; break; case SIGSEGV: case SIGFPE: case SIGBUS: case SIGABRT: //FM_LOG_TRACE("RE了"); PROBLEM::time_usage = 0; PROBLEM::memory_usage = 0; PROBLEM::result = JUDGE_CONF::RE; break; default: //FM_LOG_TRACE("不知道哪儿跪了"); PROBLEM::time_usage = 0; PROBLEM::memory_usage = 0; PROBLEM::result = JUDGE_CONF::RE; break; } ptrace(PTRACE_KILL, executive, NULL, NULL); break; } //MLE PROBLEM::memory_usage = std::max((long int)PROBLEM::memory_usage, rused.ru_minflt * (getpagesize() / JUDGE_CONF::KILO)); if (PROBLEM::memory_usage > PROBLEM::memory_limit) { PROBLEM::time_usage = 0; PROBLEM::memory_usage = 0; PROBLEM::result = JUDGE_CONF::MLE; FM_LOG_TRACE("Well, Memory Limit Exceeded."); ptrace(PTRACE_KILL, executive, NULL, NULL); break; } //获得子进程的寄存器,目的是为了获知其系统调用 if (ptrace(PTRACE_GETREGS, executive, NULL, ®s) < 0) { FM_LOG_WARNING("ptrace PTRACE_GETREGS failed"); exit(JUDGE_CONF::EXIT_JUDGE); } #ifdef __i386__ syscall_id = regs.orig_eax; #else syscall_id = regs.orig_rax; #endif //检查系统调用是否合法 if (syscall_id > 0 && !is_valid_syscall(PROBLEM::lang, syscall_id, executive, regs)) { FM_LOG_WARNING("restricted fuction %d\n", syscall_id); if (syscall_id == SYS_rt_sigprocmask){ FM_LOG_WARNING("The glibc failed."); } else { //FM_LOG_WARNING("%d\n", SYS_write); FM_LOG_WARNING("restricted fuction table"); } PROBLEM::result = JUDGE_CONF::RE; ptrace(PTRACE_KILL, executive, NULL, NULL); break; } if (ptrace(PTRACE_SYSCALL, executive, NULL, NULL) < 0) { FM_LOG_WARNING("ptrace PTRACE_SYSCALL failed."); exit(JUDGE_CONF::EXIT_JUDGE); } } } //这儿关于time_usage和memory_usage计算的有点混乱 //主要是为了减轻web的任务 //只要不是AC,就把time_usage和memory_usage归0 if (PROBLEM::result == JUDGE_CONF::SE){ PROBLEM::time_usage += (rused.ru_utime.tv_sec * 1000 + rused.ru_utime.tv_usec / 1000); PROBLEM::time_usage += (rused.ru_stime.tv_sec * 1000 + rused.ru_stime.tv_usec / 1000); } }
/* * 编译源代码 */ static void compiler_source_code() { pid_t compiler = fork(); int status = 0; if (compiler < 0) { FM_LOG_WARNING("error fork compiler"); exit(JUDGE_CONF::EXIT_COMPILE); } else if (compiler == 0) { //子进程,编译程序 log_add_info("compiler"); stdout = freopen(PROBLEM::stdout_file_compiler.c_str(), "w", stdout); stderr = freopen(PROBLEM::stderr_file_compiler.c_str(), "w", stderr); if (stdout == NULL || stderr == NULL) { FM_LOG_WARNING("error to freopen in compiler: stdout(%p) stderr(%p)", stdout, stderr); exit(JUDGE_CONF::EXIT_COMPILE); } malarm(ITIMER_REAL, JUDGE_CONF::COMPILE_TIME_LIMIT);//设置编译时间限制 switch (PROBLEM::lang) { case JUDGE_CONF::LANG_C: FM_LOG_TRACE("Start: gcc -o %s %s -static -w -lm -std=c99 -O2 -DONLINE_JUDGE", PROBLEM::exec_file.c_str(), PROBLEM::code_path.c_str()); execlp("gcc", "gcc", "-o", PROBLEM::exec_file.c_str(), PROBLEM::code_path.c_str(), "-static", "-w", "-lm", "-std=c99", "-O2", "-DONLINE_JUDGE", NULL); break; case JUDGE_CONF::LANG_CPP: FM_LOG_TRACE("Start: g++ -o %s %s -static -w -lm -O2 -DONLINE_JUDGE", PROBLEM::exec_file.c_str(), PROBLEM::code_path.c_str()); execlp("g++", "g++", "-o", PROBLEM::exec_file.c_str(), PROBLEM::code_path.c_str(), "-static", "-w", "-lm", "-O2", "-std=c++11", "-DONLINE_JUDGE", NULL); break; case JUDGE_CONF::LANG_JAVA: FM_LOG_TRACE("Start:javac %s -d %s", PROBLEM::code_path.c_str(), PROBLEM::run_dir.c_str()); execlp("javac", "javac", PROBLEM::code_path.c_str(), "-d", PROBLEM::run_dir.c_str(), NULL); //在这里增加新的语言支持 } FM_LOG_WARNING("exec compiler error"); exit(JUDGE_CONF::EXIT_COMPILE); } else { //父进程 pid_t w = waitpid(compiler, &status, WUNTRACED); //阻塞等待子进程结束 if (w == -1) { FM_LOG_WARNING("waitpid error"); exit(JUDGE_CONF::EXIT_COMPILE); } FM_LOG_TRACE("compiler finished"); if (WIFEXITED(status)) { //编译程序自行退出 if (EXIT_SUCCESS == WEXITSTATUS(status)) { FM_LOG_TRACE("compile succeeded."); } else if (JUDGE_CONF::GCC_COMPILE_ERROR == WEXITSTATUS(status)){ //编译错误 FM_LOG_TRACE("compile error"); PROBLEM::result = JUDGE_CONF::CE; get_compile_error_message(); exit(JUDGE_CONF::EXIT_OK); } else { FM_LOG_WARNING("Unknown error occur when compiling the source code.Exit status %d", WEXITSTATUS(status)); exit(JUDGE_CONF::EXIT_COMPILE); } } else { //编译程序被终止 if (WIFSIGNALED(status)){ if (SIGALRM == WTERMSIG(status)) { FM_LOG_WARNING("Compile time out"); PROBLEM::result = JUDGE_CONF::CE; PROBLEM::extra_message = "Compile Out of Time Limit"; exit(JUDGE_CONF::EXIT_OK); } else { FM_LOG_WARNING("Unknown signal when compile the source code."); } } else if (WIFSTOPPED(status)){ FM_LOG_WARNING("The compile process stopped by signal"); } else { FM_LOG_WARNING("I don't kwon why the compile process stopped"); } exit(JUDGE_CONF::EXIT_COMPILE); } } }