Beispiel #1
0
void print_solution() {
    FM_LOG_DEBUG("-- Solution Information --");
    FM_LOG_MONITOR("solution id %d", oj_solution.sid);
    FM_LOG_TRACE("problem id    %d", oj_solution.pid);
    FM_LOG_TRACE("language(%d)   %s", oj_solution.lang, languages[oj_solution.lang]);
    FM_LOG_TRACE("time limit    %d ms", oj_solution.time_limit);
    FM_LOG_TRACE("memory limit  %d KB", oj_solution.memory_limit);
    FM_LOG_DEBUG("work dir      %s", oj_solution.work_dir);
    FM_LOG_DEBUG("data dir      %s", oj_solution.data_dir);
}
Beispiel #2
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;
}
/*
 * 输入输出重定向
 */
static
void io_redirect() {
    FM_LOG_TRACE("Start to redirect the IO.");
    stdin = freopen(PROBLEM::input_file.c_str(), "r", stdin);
    stdout = freopen(PROBLEM::exec_output.c_str(), "w", stdout);
    //stderr = freopen("/dev/null", "w", stderr);

    if (stdin == NULL || stdout == NULL) {
        FM_LOG_WARNING("It occur a error when freopen: stdin(%p) stdout(%p)", stdin, stdout);
        exit(JUDGE_CONF::EXIT_PRE_JUDGE);
    }
    FM_LOG_TRACE("redirect io is OK.");
}
Beispiel #4
0
void ThreadWork() {
    while (isRunning) {
        oj_solution_t oj_solution = ProcessQueue.GetFrontAndPop();
        pthread_t ptid = pthread_self();
        FM_LOG_TRACE("Thread id: %d", ptid);
        run(oj_solution);
    }
}
Beispiel #5
0
void truncate_upload_file(char *file_path) {
    off_t size = file_size(file_path);
    if (size > MAX_UPLOAD_FILE_SIZE) {
        FM_LOG_TRACE("truncate_upload_file: %s %d %d", file_path, size, MAX_UPLOAD_FILE_SIZE);
        if (truncate(file_path, MAX_UPLOAD_FILE_SIZE) != 0) {
            FM_LOG_WARNING("truncate upload file %s failed: %s", file_path, strerror(errno));
        }
    }
}
Beispiel #6
0
void SendWork() {
    while (isRunning) {
        auto item = SendQueue.GetFrontAndPop();
        pthread_t ptid = pthread_self();
        FM_LOG_TRACE("Send thread id: %d", ptid);
        if (item.first == EXIT_OK) {
            update_result(item.second);
        } else {
            update_system_error(item.first, item.second);
        }
    }
}
Beispiel #7
0
void log_close()
{
    if (log_opened)
    {
        FM_LOG_TRACE("log_close");
        fclose(log_fp);
        free(log_filename);
        log_fp       = NULL;
        log_filename = NULL;
        log_opened   = 0;
    }
}
Beispiel #8
0
void io_redirect(const char *input_file, const char *stdout_file, const char *stderr_file) {
    // io_redirect
    stdin = freopen(input_file, "r", stdin);
    stdout = freopen(stdout_file, "w", stdout);
    stderr = freopen(stderr_file, "a+", stderr);

    if (stdin == nullptr || stdout == nullptr || stderr == nullptr) {
        FM_LOG_FATAL("error freopen: stdin(%p) stdout(%p), stderr(%p)", stdin, stdout, stderr);
        exit(EXIT_PRE_JUDGE);
    }
    FM_LOG_TRACE("io redirect ok!");
}
Beispiel #9
0
int parse_arguments(char *str, oj_solution_t &oj_solution) {
    int number = sscanf(str, "%s %d %s %s %s %s %s", oj_solution.sid, &oj_solution.cid,
                        oj_solution.pid, oj_solution.language,
                        oj_solution.time_limit, oj_solution.memory_limit, oj_solution.token);
    FM_LOG_TRACE("sid=%s cid=%d  pid=%s  language=%s  timeLimit=%s ms  memoryLimit=%s KB %s",
                 oj_solution.sid, oj_solution.cid, oj_solution.pid, oj_solution.language,
                 oj_solution.time_limit, oj_solution.memory_limit, oj_solution.token);
    if (number < 6) {
        return -1;
    }
    return 0;
}
Beispiel #10
0
void set_security_option() {
    if (oj_solution.lang != LANG_JAVA && oj_solution.lang != LANG_KOTLIN
#ifdef FAST_JUDGE
        && oj_solution.lang != LANG_PYTHON3 && oj_solution.lang != LANG_PYTHON27
#endif
            ) {
        char cwd[PATH_SIZE];
        char *tmp = getcwd(cwd, PATH_SIZE - 1);
        if (tmp == nullptr) {
            FM_LOG_FATAL("getcwd failed: %s", strerror(errno));
            exit(EXIT_SET_SECURITY);
        }

        // chroot, current directory will be the root dir
        if (EXIT_SUCCESS != chroot(cwd)) {
            FM_LOG_FATAL("chroot(%s) failed: %s", cwd, strerror(errno));
            exit(EXIT_SET_SECURITY);
        }
        FM_LOG_DEBUG("chroot(%s)", cwd);
    }

    FM_LOG_TRACE("set_security_option ok");
}
Beispiel #11
0
/*
 * 输出判题结果到结果文件
 */
static
void output_result() {
    FILE* result_file = fopen(PROBLEM::result_file.c_str(), "w");
    switch (PROBLEM::result){
        case 1:PROBLEM::status = "Compile Error";break;
        case 2:PROBLEM::status = "Time Limit Exceeded";break;
        case 3:PROBLEM::status = "Memory Limit Exceeded";break;
        case 4:PROBLEM::status = "Output Limit Exceeded";break;
        case 5:PROBLEM::status = "Runtime Error";break;
        case 6:PROBLEM::status = "Wrong Answer";break;
        case 7:PROBLEM::status = "Accepted";break;
        case 8:PROBLEM::status = "Presentation Error";break;
        default:PROBLEM::status = "System Error";break;
    }
    fprintf(result_file, "%s\n", PROBLEM::status.c_str());
    fprintf(result_file, "%d\n", PROBLEM::time_usage);
    fprintf(result_file, "%d\n", PROBLEM::memory_usage);
    fprintf(result_file, "%s\n", PROBLEM::extra_message.c_str());

    FM_LOG_TRACE("The final result is %s %d %d %s",
            PROBLEM::status.c_str(), PROBLEM::time_usage,
            PROBLEM::memory_usage, PROBLEM::extra_message.c_str());
}
Beispiel #12
0
void set_limit(off_t fsize) {
    rlimit lim{};

    // Set CPU time limit round up, raise SIGXCPU
    lim.rlim_max = (oj_solution.time_limit + 999) / 1000 + 1;
    lim.rlim_cur = lim.rlim_max;
    if (setrlimit(RLIMIT_CPU, &lim) < 0) {
        FM_LOG_FATAL("setrlimit RLIMIT_CPU failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }

    if (oj_solution.lang <= LANG_PASCAL) {
        // Memory control, raise SIGSEGV
        lim.rlim_cur = lim.rlim_max = (STD_MB << 10) + oj_solution.memory_limit * STD_KB;
        if (setrlimit(RLIMIT_AS, &lim) < 0) {
            FM_LOG_FATAL("setrlimit RLIMIT_AS failed: %s", strerror(errno));
            exit(EXIT_SET_LIMIT);
        }
    }

    // Stack space, raise SIGSEGV
    lim.rlim_cur = lim.rlim_max = stack_size_limit * STD_KB;
    if (setrlimit(RLIMIT_STACK, &lim) < 0) {
        FM_LOG_FATAL("setrlimit RLIMIT_STACK failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }

    // Output file size limit, raise SIGXFSZ
    lim.rlim_cur = lim.rlim_max = (rlim_t) (4 * MAX_LOG_FILE_SIZE);
    if (setrlimit(RLIMIT_FSIZE, &lim) < 0) {
        FM_LOG_FATAL("setrlimit RLIMIT_FSIZE failed: %s", strerror(errno));
        exit(EXIT_SET_LIMIT);
    }
    FM_LOG_DEBUG("File size limit: %d", lim.rlim_max);

    FM_LOG_TRACE("set execute limit ok");
}
Beispiel #13
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, &regs) < 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;
}
Beispiel #14
0
void run_solution() {
    FM_LOG_DEBUG("run_solution");
#ifndef FAST_JUDGE
    if (oj_solution.lang == LANG_PYTHON27) {
        copy_python_runtime_python2(oj_solution.work_dir);
        FM_LOG_DEBUG("copy_python_runtime");
    } else if (oj_solution.lang == LANG_PYTHON3) {
        copy_python_runtime_python3(oj_solution.work_dir);
        FM_LOG_DEBUG("copy_python_runtime");
    }
#endif

    check_spj();

    struct dirent **namelist;
    int num_of_test;

    num_of_test = scandir(oj_solution.data_dir, &namelist, data_filter, alphasort);
    if (num_of_test < 0) {
        FM_LOG_FATAL("scan data directory failed: %s", strerror(errno));
        exit(EXIT_PRE_JUDGE_DAA);
    }

    int first_failed_test = 0;
    char input_file[PATH_SIZE];
    char output_file_std[PATH_SIZE];
    char stdout_file_executive[PATH_SIZE];
    char stderr_file_executive[PATH_SIZE];

    snprintf(stderr_file_executive, PATH_SIZE, "%s/stderr_executive.txt", oj_solution.work_dir);
    FM_LOG_DEBUG("start run solution (%d cases)", num_of_test);

    for (int i = 0; i < num_of_test; ++i) {
        update_solution_status(oj_solution.cid, oj_solution.sid, OJ_RUN, i + 1);

        prepare_files(namelist[i]->d_name, input_file, output_file_std, stdout_file_executive);

        FM_LOG_TRACE("run case: %d", i + 1);

        bool result = judge(input_file, output_file_std, stdout_file_executive, stderr_file_executive);

        if (oj_solution.result != OJ_AC && !first_failed_test) {
            first_failed_test = i + 1;
        }

        if (!result && oj_solution.judge_type == ACM) {
            break;
        }
    }

    for (int i = 0; i < num_of_test; ++i) {
        free(namelist[i]);
    }
    free(namelist);

#ifndef FAST_JUDGE
    if (oj_solution.lang == LANG_PYTHON27 || oj_solution.lang == LANG_PYTHON3) {
        clean_workdir(oj_solution.work_dir);
    }
#endif

    output_acm_result(oj_solution.result, oj_solution.time_usage, oj_solution.memory_usage, first_failed_test);
}
Beispiel #15
0
/*
 * #error "This make CE"
 * #warning "Just warning message"
 * #include </dev/core>
 * #include </dev/zero>
 * #include </dev/random>
 * #include </etc/passwd>
 * #include <../../../etc/passwd>
 * egrep '^\s*#include\s*[<"][./].*[>"]' Main.cc
 */
void compile() {
    update_solution_status(oj_solution.cid, oj_solution.sid, OJ_COM, 0);
    char stdout_compiler[PATH_SIZE];
    char stderr_compiler[PATH_SIZE];
    snprintf(stdout_compiler, PATH_SIZE, "%s/stdout_compiler.txt", oj_solution.work_dir);
    snprintf(stderr_compiler, PATH_SIZE, "%s/stderr_compiler.txt", oj_solution.work_dir);

    pid_t compiler = fork();  // create a child process for compiler

    if (compiler < 0) {
        FM_LOG_FATAL("fork compiler failed: %s", strerror(errno));
        exit(EXIT_FORK_COMPILER);
    } else if (compiler == 0) {
        // child process: run compiler
        log_add_info("compiler");

        set_compile_limit();

        stdout = freopen(stdout_compiler, "w", stdout);
        stderr = freopen(stderr_compiler, "w", stderr);
        if (stdout == nullptr || stderr == nullptr) {
            FM_LOG_FATAL("error freopen: stdout(%p), stderr(%p)", stdout, stderr);
            exit(EXIT_COMPILE_IO);
        }
        print_user_group();
        print_word_dir();

        switch (oj_solution.lang) {
            case LANG_C99:
                print_compiler(CP_C99);
                execvp(CP_C99[0], (char *const *) CP_C99);
                break;
            case LANG_C11:
                print_compiler(CP_C11);
                execvp(CP_C11[0], (char *const *) CP_C11);
                break;
            case LANG_CPP98:
                print_compiler(CP_CC98);
                execvp(CP_CC98[0], (char *const *) CP_CC98);
                break;
            case LANG_CPP11:
                print_compiler(CP_CC11);
                execvp(CP_CC11[0], (char *const *) CP_CC11);
                break;
            case LANG_CPP14:
                print_compiler(CP_CC14);
                execvp(CP_CC14[0], (char *const *) CP_CC14);
                break;
            case LANG_CPP17:
                print_compiler(CP_CC98);
                execvp(CP_CC98[0], (char *const *) CP_CC17);
                break;
            case LANG_PASCAL:
                print_compiler(CP_PAS);
                execvp(CP_PAS[0], (char *const *) CP_PAS);
                break;
            case LANG_JAVA:
                print_compiler(CP_J);
                execvp(CP_J[0], (char *const *) CP_J);
                break;
            case LANG_PYTHON27:
                print_compiler(CP_PY27);
                execvp(CP_PY27[0], (char *const *) CP_PY27);
                break;
            case LANG_PYTHON3:
                print_compiler(CP_PY3);
                execvp(CP_PY3[0], (char *const *) CP_PY3);
                break;
            case LANG_KOTLIN:
                print_compiler(CP_KT);
                execvp(CP_KT[0], (char *const *) CP_KT);
                break;
            default:
                FM_LOG_FATAL("Unknown language %d", oj_solution.lang);
                break;
        }

        // execvp error
        FM_LOG_FATAL("execvp compiler error");
        exit(EXIT_COMPILE_EXEC);
    } else {
        // parent process: Judger
        int status = 0;
        if (waitpid(compiler, &status, WUNTRACED) == -1) {
            FM_LOG_FATAL("waitpid for compiler failed: %s", strerror(errno));
            exit(EXIT_COMPILE_ERROR);  // SE
        }
        FM_LOG_DEBUG("compiler finished");

        if ((oj_solution.lang == LANG_PYTHON27 || oj_solution.lang == LANG_PYTHON3) && file_size(stderr_compiler)) {
            FM_LOG_TRACE("compile error");
            output_acm_result(OJ_CE, 0, 0, 0);
            exit(EXIT_OK);
        }

        if (WIFEXITED(status)) {  // normal termination
            if (EXIT_SUCCESS == WEXITSTATUS(status)) {
                FM_LOG_DEBUG("compile succeeded");
            } else if (GCC_COMPILE_ERROR == WEXITSTATUS(status)) {
                FM_LOG_TRACE("compile error");
                output_acm_result(OJ_CE, 0, 0, 0);
                exit(EXIT_OK);
            } else {
                if (fix_gcc_result(stderr_compiler)) {
                    FM_LOG_WARNING("Compiler Limit Exceeded!");
                    output_acm_result(OJ_CE, 0, 0, 0);
                    exit(EXIT_OK);
                } else {
                    FM_LOG_FATAL("compiler unknown exit status %d", WEXITSTATUS(status));
                    output_acm_result(OJ_CE, 0, 0, 0);
                    exit(EXIT_COMPILE_ERROR);
                }
            }
        } else {
            if (WIFSIGNALED(status)) {  // killed by signal
                int signo = WTERMSIG(status);
                FM_LOG_WARNING("Compiler Limit Exceeded: %s", strsignal(signo));
                output_acm_result(OJ_CE, 0, 0, 0);
                stderr = freopen(stderr_compiler, "w", stderr);
                fprintf(stderr, "Compiler Limit Exceeded: %s\n", strsignal(signo));
                exit(EXIT_OK);
            } else if (WIFSTOPPED(status)) {  // stopped by signal
                int signo = WSTOPSIG(status);
                FM_LOG_FATAL("stopped by signal: %s\n", strsignal(signo));
            } else {
                FM_LOG_FATAL("unknown stop reason, status(%d)", status);
            }
            exit(EXIT_COMPILE_ERROR);  // SE
        }
    }
}
Beispiel #16
0
int main(int argc, char *argv[], char *envp[]) {
    log_open(LOG_FILE);
    FM_LOG_TRACE("---");
    check_pid();

    int sockfd;
    socklen_t clilen;
    struct sockaddr_in serv_addr{};
    struct sockaddr_in cli_addr{};
    const char *cfg_file;

    if (argc > 1) {
        cfg_file = argv[1];
    } else {
        cfg_file = DEFAULT_CFG_FILE;
    }
    read_config(cfg_file);
    FM_LOG_TRACE("read_config");

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        fatal_error("ERROR opening socket");
    }
    FM_LOG_TRACE("socket");

    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    if (inet_aton(oj_config.ip, &serv_addr.sin_addr) == 0) {
        serv_addr.sin_addr.s_addr = INADDR_ANY;
    }
    serv_addr.sin_port = htons(oj_config.port);
    FM_LOG_NOTICE("IP address: %s %s", oj_config.ip, inet_ntoa(serv_addr.sin_addr));
    FM_LOG_NOTICE("port: %d %d", oj_config.port, ntohs(serv_addr.sin_port));

    int yes = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        fatal_error("setsockopt SO_REUSEADDR failed");
    }

    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        fatal_error("ERROR on binding");
    }
    FM_LOG_TRACE("bind");

    clilen = sizeof(cli_addr);

    if (listen(sockfd, oj_config.backlog) < 0) {
        fatal_error("ERROR on listening");
    }
    FM_LOG_NOTICE("listen  backlog: %d", oj_config.backlog);

    if (daemon(0, 0) == -1) {
        FM_LOG_FATAL("Cannot daemonize");
        pidfile_remove(pfh);

        exit(EXIT_FAILURE);
    }

    print_word_dir();
    print_user_group();

    pidfile_write(pfh);

    struct sigaction sa{};
    sa.sa_handler = signal_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGTERM, &sa, nullptr) == -1) {   // install signal hander for timeout
        FM_LOG_FATAL("cannot handle SIGTERM");
        exit(EXIT_FAILURE);
    } else {
        FM_LOG_DEBUG("set signal_handler");
    }
    for (int i = 0; i < oj_config.thread_num; i++) {
        std::thread t(ThreadWork);
        t.detach();
    }
    FM_LOG_NOTICE("thread count: %d", oj_config.thread_num);

    std::thread(SendWork).detach();

    while (isRunning) {
        int newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
        if (newsockfd != -1) {
            work(newsockfd, cli_addr);
        }
    }

    pidfile_remove(pfh);
    close(sockfd);
    return 0;
}
Beispiel #17
0
void send_multi_result(char *file_path, oj_solution_t &oj_solution) {
    FM_LOG_TRACE("send_multi_result");
    CURL *curl;

    CURLM *multi_handle;
    int still_running = 1;

    struct curl_httppost *formpost = nullptr;
    struct curl_httppost *lastptr = nullptr;
    struct curl_slist *headerlist = nullptr;
    static const char buf[] = "Expect:";
    const size_t size = 25;
    char data[size] = {0};
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "sid",
                 CURLFORM_COPYCONTENTS, oj_solution.sid,
                 CURLFORM_END);

    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "token",
                 CURLFORM_COPYCONTENTS, oj_solution.token,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.cid);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "cid",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.result);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "result",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.time_usage);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "time",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.memory_usage);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "memory",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    snprintf(data, size, "%d", oj_solution.test);
    curl_formadd(&formpost,
                 &lastptr,
                 CURLFORM_COPYNAME, "test",
                 CURLFORM_COPYCONTENTS, data,
                 CURLFORM_END);

    if (file_path != NULL && access(file_path, F_OK) != -1) {
        truncate_upload_file(file_path);
        FM_LOG_NOTICE("will upload error file %s", file_path);
        curl_formadd(&formpost,
                     &lastptr,
                     CURLFORM_COPYNAME, "error",
                     CURLFORM_FILE, file_path,
                     CURLFORM_END);
    }

    FM_LOG_TRACE("try curl_easy_init");
    curl = curl_easy_init();
    multi_handle = curl_multi_init();

    headerlist = curl_slist_append(headerlist, buf);
    if (curl && multi_handle) {
        FM_LOG_TRACE("curl_multi_init OK");
        curl_easy_setopt(curl, CURLOPT_URL, oj_config.api_url);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

        curl_multi_add_handle(multi_handle, curl);

        curl_multi_perform(multi_handle, &still_running);

        do {
            struct timeval timeout{};
            int rc; /* select() return code */
            CURLMcode mc; /* curl_multi_fdset() return code */

            fd_set fdread;
            fd_set fdwrite;
            fd_set fdexcep;
            int maxfd = -1;

            long curl_timeo = -1;

            FD_ZERO(&fdread);
            FD_ZERO(&fdwrite);
            FD_ZERO(&fdexcep);

            /* set a suitable timeout to play around with */
            timeout.tv_sec = 1;
            timeout.tv_usec = 0;

            curl_multi_timeout(multi_handle, &curl_timeo);
            if (curl_timeo >= 0) {
                timeout.tv_sec = curl_timeo / 1000;
                if (timeout.tv_sec > 1)
                    timeout.tv_sec = 1;
                else
                    timeout.tv_usec = (curl_timeo % 1000) * 1000;
            }

            /* get file descriptors from the transfers */
            mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);

            if (mc != CURLM_OK) {
                fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
                break;
            }

            if (maxfd == -1) {
#ifdef _WIN32
                Sleep(100);
                rc = 0;
#else
                /* Portable sleep for platforms other than Windows. */
                struct timeval wait = {0, 100 * 1000}; /* 100ms */
                rc = select(0, NULL, NULL, NULL, &wait);
#endif
            } else {
                /* Note that on some platforms 'timeout' may be modified by select().
                   If you need access to the original value save a copy beforehand. */
                rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
            }

            switch (rc) {
                case -1:
                    /* select error */
                    break;
                case 0:
                default:
                    /* timeout or readable/writable sockets */
                    curl_multi_perform(multi_handle, &still_running);
                    break;
            }
        } while (still_running);

        curl_multi_cleanup(multi_handle);

        curl_easy_cleanup(curl);

        curl_formfree(formpost);

        curl_slist_free_all(headerlist);
        FM_LOG_DEBUG("send_multi_result finished");
    } else {
        FM_LOG_FATAL("cannot init curl: %s", strerror(errno));
        update_system_error(EXIT_CURL_ERROR, oj_solution);
    }
}
Beispiel #18
0
static
int compare_output(std::string file_std, std::string file_exec) {
    //这里可以不用写的
    //仔细研究一下diff及其参数即可
    //实现各种功能
    FILE *fp_std = fopen(file_std.c_str(), "r");
    if (fp_std == NULL) {
        FM_LOG_WARNING("Open standard output file failed.");
        exit(JUDGE_CONF::EXIT_COMPARE);
    }

    FILE *fp_exe = fopen(file_exec.c_str(), "r");
    if (fp_exe == NULL) {
        FM_LOG_WARNING("Open executive output file failed.");
        exit(JUDGE_CONF::EXIT_COMPARE);
    }
    int a, b, Na = 0, Nb = 0;
    enum {
        AC = JUDGE_CONF::AC,
        PE = JUDGE_CONF::PE,
        WA = JUDGE_CONF::WA
    }status = AC;
    while (true) {
        a = fgetc(fp_std);
        b = fgetc(fp_exe);
        Na++, Nb++;

        //统一\r和\n之间的区别
        if (a == '\r') {
            a = fgetc(fp_std);
            Na++;
        }
        if (b == '\r') {
            b = fgetc(fp_std);
            Nb++;
        }
#define is_space_char(a) ((a == ' ') || (a == '\t') || (a == '\n'))

        if (feof(fp_std) && feof(fp_exe)){
            //文件结束
            break;
        } else if (feof(fp_std) || feof(fp_exe)) {
            //如果只有一个文件结束
            //但是另一个文件的末尾是回车
            //那么也当做AC处理
            FILE *fp_tmp;
            if (feof(fp_std)) {
                if (!is_space_char(b)) {
                    FM_LOG_TRACE("Well, Wrong Answer.");
                    status = WA;
                    break;
                }
                fp_tmp = fp_exe;
            } else {
                if (!is_space_char(a)) {
                    FM_LOG_TRACE("Well, Wrong Answer.");
                    status = WA;
                    break;
                }
                fp_tmp = fp_std;
            }
            int c;
            while ((c = fgetc(fp_tmp)) != EOF) {
                if (c == '\r') c = '\n';
                if (!is_space_char(c)) {
                    FM_LOG_TRACE("Well, Wrong Answer.");
                    status = WA;
                    break;
                }
            }
            break;
        }

        //如果两个字符不同
        if (a != b) {
            status = PE;
            //过滤空白字符
            if (is_space_char(a) && is_space_char(b)) {
                continue;
            }
            if (is_space_char(a)) {
                //a是空白字符,过滤,退回b以便下一轮循环
                ungetc(b, fp_exe);
                Nb--;
            } else if (is_space_char(b)) {
                ungetc(a, fp_std);
                Na--;
            } else {
                FM_LOG_TRACE("Well, Wrong Answer.");
                status = WA;
                break;
            }
        }
    }
    fclose(fp_std);
    fclose(fp_exe);
    return status;
}
Beispiel #19
0
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.");
        }
    }
}
Beispiel #20
0
/*
 * 编译源代码
 */
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);
        }
    }
}
Beispiel #21
0
/*
 * 执行用户提交的程序
 */
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, &regs) < 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);
    }

}
Beispiel #22
0
int oj_compare_output(const char *file_out, const char *file_user) {
    FM_LOG_TRACE("start compare");
    FILE *fp_std = fopen(file_out, "r");
    if (fp_std == nullptr) {
        FM_LOG_FATAL("open standard output file (%s) failed: %s", file_out, strerror(errno));
        exit(EXIT_COMPARE);
    }

    FILE *fp_exe = fopen(file_user, "r");
    if (fp_exe == nullptr) {
        FM_LOG_FATAL("open user output file (%s) failed: %s", file_user, strerror(errno));
        exit(EXIT_COMPARE);
    }

    int a, b, Na = 0, Nb = 0;
    enum {
        AC = OJ_AC,
        PE = OJ_PE,
        WA = OJ_WA
    } status = AC;

    while (true) {
        /*
         * Windows / DOS uses '\r\n';
         * Unix / Linux / OS X uses '\n';
         * Macs before OS X use '\r';
         * TODO(power): out file with '\r' line ending get incorrect PE
         */
        while ((a = fgetc(fp_std)) == '\r') {}
        while ((b = fgetc(fp_exe)) == '\r') {}
        Na++, Nb++;

        // deal with '\r' and '\n'
        if (a == '\r') a = '\n';
        if (b == '\r') b = '\n';

        if (feof(fp_std) && feof(fp_exe)) {
            break;
        } else if (feof(fp_std) || feof(fp_exe)) {
            // deal with tailing white spaces
            FILE *fp_tmp;
            if (feof(fp_std)) {
                FM_LOG_TRACE("std out file ended");
                if (!is_space_char(b)) {
                    FM_LOG_TRACE("WA exe['%c':0x%x @%d]", b, b, Nb);
                    status = WA;
                    break;
                }
                fp_tmp = fp_exe;
            } else { /* feof(fp_exe) */
                FM_LOG_TRACE("user out file ended");
                if (!is_space_char(a)) {
                    FM_LOG_TRACE("WA std['%c':0x%x @%d]", a, a, Na);
                    status = WA;
                    break;
                }
                fp_tmp = fp_std;
            }
            int c;
            while (c = fgetc(fp_tmp), c != EOF) {
                if (c == '\r') c = '\n';
                if (!is_space_char(c)) {
                    FM_LOG_TRACE("WA ['%c':0x%x]", c, c);
                    status = WA;
                    break;
                }
            }
            break;
        }

        if (a != b) {
            status = PE;
            if (is_space_char(a) && is_space_char(b)) {
                continue;
            }
            if (is_space_char(a)) {
                ungetc(b, fp_exe);
                Nb--;
            } else if (is_space_char(b)) {
                ungetc(a, fp_std);
                Na--;
            } else {
                FM_LOG_TRACE("WA ['%c':0x%x @%d] : ['%c':0x%x @%d]", a, a, Na, b, b, Nb);
                status = WA;
                break;
            }
        }
    }  // end of while

    fclose(fp_std);
    fclose(fp_exe);

    if (status == WA || status == PE) {
        make_diff_out2(file_out, file_user, oj_solution.work_dir, file_out);
    }
    FM_LOG_TRACE("compare finished, result=%s", status == AC ? "AC" : (status == PE ? "PE" : "WA"));
    return status;
}
Beispiel #23
0
void run(oj_solution_t &oj_solution) {
    if (oj_solution.cid > 0) {
        snprintf(oj_solution.work_dir, PATH_SIZE, "%s/c%d", oj_config.temp_dir, oj_solution.cid);
    } else {
        strncpy(oj_solution.work_dir, oj_config.temp_dir, strlen(oj_config.temp_dir) + 1);
    }
    char stderr_file[PATH_SIZE];
    snprintf(stderr_file, PATH_SIZE, "%s/%s/error.txt", oj_solution.work_dir, oj_solution.sid);
    FM_LOG_NOTICE("/usr/local/bin/powerjudge -s %s -p %s -l %s -t %s -m %s -w %s -D %s",
                  oj_solution.sid, oj_solution.pid, oj_solution.language,
                  oj_solution.time_limit, oj_solution.memory_limit,
                  oj_solution.work_dir, oj_config.data_dir);
    pid_t pid = fork();
    if (pid < 0) {
        FM_LOG_FATAL("fork judger failed: %s", strerror(errno));
        SendQueue.push(std::make_pair(EXIT_FORK_ERROR, oj_solution));
    } else if (pid == 0) {
        execl("/usr/local/bin/powerjudge",
              "/usr/local/bin/powerjudge",
              "-s", oj_solution.sid,
              "-p", oj_solution.pid,
              "-l", oj_solution.language,
              "-t", oj_solution.time_limit,
              "-m", oj_solution.memory_limit,
              "-w", oj_solution.work_dir,
              "-D", oj_config.data_dir,
              "-c", std::to_string(oj_solution.cid).c_str(),
              NULL);
        stderr = freopen(stderr_file, "a+", stderr);
        FM_LOG_FATAL("exec error: %s", strerror(errno));
        SendQueue.push(std::make_pair(EXIT_EXEC_ERROR, oj_solution));
    } else {
        int status = 0;
        FM_LOG_TRACE("process ID=%d", pid);
        if (waitpid(pid, &status, WUNTRACED) == -1) {
            FM_LOG_FATAL("waitpid for judger failed: %s", strerror(errno));
        }

        if (WIFEXITED(status))    // normal termination
        {
            if (EXIT_SUCCESS == WEXITSTATUS(status)) {
                FM_LOG_DEBUG("judge succeeded");
                SendQueue.push(std::make_pair(EXIT_OK, oj_solution));
            } else if (EXIT_COMPILE_ERROR == WEXITSTATUS(status)) {
                FM_LOG_TRACE("compile error");
                SendQueue.push(std::make_pair(EXIT_OK, oj_solution));
            } else if (EXIT_JUDGE == WEXITSTATUS(status)) {
                FM_LOG_TRACE("judge error");
                SendQueue.push(std::make_pair(OJ_SE, oj_solution));
            } else {
                FM_LOG_TRACE("judge error");
                SendQueue.push(std::make_pair(WEXITSTATUS(status), oj_solution));
            }
        } else {
            if (WIFSIGNALED(status))    // killed by signal
            {
                int signo = WTERMSIG(status);
                FM_LOG_WARNING("judger killed by signal: %s", strsignal(signo));
                SendQueue.push(std::make_pair(signo, oj_solution));
            } else if (WIFSTOPPED(status))      // stopped by signal
            {
                int signo = WSTOPSIG(status);
                FM_LOG_FATAL("judger stopped by signal: %s\n", strsignal(signo));
                SendQueue.push(std::make_pair(signo, oj_solution));
            } else {
                FM_LOG_FATAL("judger stopped with unknown reason, status(%d)", status);
                SendQueue.push(std::make_pair(EXIT_UNKNOWN, oj_solution));
            }
        }
    }
}