/* * 对SpecialJudge程序的安全性控制 * 毕竟不是自己写的代码,得防着点 */ static void security_control_spj() { struct passwd *nobody = getpwnam("nobody"); if (nobody == NULL) { FM_LOG_WARNING("Well, where is nobody? I cannot live without him. %d: %s", errno, strerror(errno)); exit(JUDGE_CONF::EXIT_SET_SECURITY); } if (EXIT_SUCCESS != chdir(PROBLEM::run_dir.c_str())) { FM_LOG_WARNING("chdir(%s) failed, %d: %s", PROBLEM::run_dir.c_str(), errno, strerror(errno)); exit(JUDGE_CONF::EXIT_SET_SECURITY); } char cwd[1024], *tmp = getcwd(cwd, 1024); if (tmp == NULL) { FM_LOG_WARNING("Oh, where i am now? I cannot getcwd. %d: %s", errno, strerror(errno)); exit(JUDGE_CONF::EXIT_SET_SECURITY); } //if (PROBLEM::spj_lang != JUDGE_CONF::LANG_JAVA) { // if (EXIT_SUCCESS != chroot(cwd)) { // FM_LOG_WARNING("chroot(%s) failed. %d: %s", cwd, errno, strerror(errno)); // exit(JUDGE_CONF::EXIT_SET_SECURITY); // } //} //if (EXIT_SUCCESS != setuid(nobody->pw_uid)) { // FM_LOG_WARNING("setuid(%d) failed. %d: %s", nobody->pw_uid, errno, strerror(errno)); // exit(JUDGE_CONF::EXIT_SET_SECURITY); //} }
/* * 解析参数 */ static void parse_arguments(int argc, char* argv[]) { int opt; extern char *optarg; while ((opt = getopt(argc, argv, "c:t:m:d:S:s")) != -1) { switch (opt) { case 'c': PROBLEM::code_path = optarg; break; case 't': PROBLEM::time_limit = atoi(optarg); break; case 'm': PROBLEM::memory_limit = atoi(optarg); break; case 's': PROBLEM::spj = true; break; case 'S': PROBLEM::spj_lang = atoi(optarg); break; case 'd': PROBLEM::run_dir = optarg; break; default: FM_LOG_WARNING("Unknown option provided: -%c %s", opt, optarg); exit(JUDGE_CONF::EXIT_BAD_PARAM); } } if (has_suffix(PROBLEM::code_path, ".cpp")) { PROBLEM::lang = JUDGE_CONF::LANG_CPP; } else if (has_suffix(PROBLEM::code_path, ".c")) { PROBLEM::lang = JUDGE_CONF::LANG_C; } else if (has_suffix(PROBLEM::code_path, ".java")) { PROBLEM::lang = JUDGE_CONF::LANG_JAVA; } else { FM_LOG_WARNING("It seems that you give me a language which I do not known now: %d", PROBLEM::lang); exit(JUDGE_CONF::EXIT_BAD_PARAM); } PROBLEM::exec_file = PROBLEM::run_dir + "/a.out"; PROBLEM::input_file = PROBLEM::run_dir + "/in.in"; PROBLEM::output_file = PROBLEM::run_dir + "/out.out"; PROBLEM::exec_output = PROBLEM::run_dir + "/out.txt"; PROBLEM::result_file = PROBLEM::run_dir + "/result.txt"; PROBLEM::stdout_file_compiler = PROBLEM::run_dir + "/stdout_file_compiler.txt"; PROBLEM::stderr_file_compiler = PROBLEM::run_dir + "/stderr_file_compiler.txt"; if (PROBLEM::lang == JUDGE_CONF::LANG_JAVA) { PROBLEM::exec_file = PROBLEM::run_dir + "/Main"; PROBLEM::time_limit *= JUDGE_CONF::JAVA_TIME_FACTOR; PROBLEM::memory_limit *= JUDGE_CONF::JAVA_MEM_FACTOR; //Java放宽内存和时间限制 } if (PROBLEM::spj) { switch (PROBLEM::spj_lang) { case 1: case 2: PROBLEM::spj_exec_file = PROBLEM::run_dir + "/SpecialJudge";break; case 3: PROBLEM::spj_exec_file = PROBLEM::run_dir + "/SpecialJudge";break; default: FM_LOG_WARNING("OMG, I really do not kwon the special judge problem language."); exit(JUDGE_CONF::EXIT_BAD_PARAM); } PROBLEM::spj_output_file = PROBLEM::run_dir + "/spj_output.txt"; } }
// 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; }
void update_system_error(int result, oj_solution_t &oj_solution) { FM_LOG_WARNING("system error %d", result); oj_solution.result = OJ_SE; char buffer[BUFF_SIZE]; snprintf(buffer, BUFF_SIZE, "%s/%s/error.txt", oj_solution.work_dir, oj_solution.sid); send_multi_result(buffer, oj_solution); }
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; }
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)); } } }
void work(int newsockfd, struct sockaddr_in cli_addr) { if (newsockfd < 0) { FM_LOG_WARNING("ERROR on accept"); return; } FM_LOG_NOTICE("connect from %s:%d", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)); char buffer[BUFF_SIZE]; bzero(buffer, BUFF_SIZE); ssize_t n = read(newsockfd, buffer, BUFF_SIZE); if (n < 0) FM_LOG_WARNING("ERROR reading from socket"); FM_LOG_NOTICE("Here is the password: %s", buffer); if (check_password(oj_config.password, buffer)) { FM_LOG_DEBUG("Authentication Ok."); n = write(newsockfd, "Authentication Ok.", 18); if (n < 0) FM_LOG_WARNING("ERROR writing to socket"); bzero(buffer, BUFF_SIZE); n = read(newsockfd, buffer, BUFF_SIZE); if (n <= 0) { FM_LOG_WARNING("ERROR reading from socket"); close(newsockfd); return; } FM_LOG_NOTICE("Here is the message: %s(%d)", buffer, n); oj_solution_t oj_solution{}; if (parse_arguments(buffer, oj_solution) < 0) { FM_LOG_WARNING("Missing some parameters."); n = write(newsockfd, "Missing some parameters.", 24); if (n < 0) FM_LOG_WARNING("ERROR writing to socket"); close(newsockfd); return; } else { n = write(newsockfd, "I got your request.", 19); if (n < 0) FM_LOG_WARNING("ERROR writing to socket"); close(newsockfd); ProcessQueue.push(oj_solution); return; } } else { FM_LOG_WARNING("Authentication Failed."); n = write(newsockfd, "Authentication Failed.", 22); if (n < 0) FM_LOG_WARNING("ERROR writing to socket"); } close(newsockfd); }
/* * 程序运行的限制 * CPU时间、堆栈、输出文件大小等 */ static void set_limit() { rlimit lim; lim.rlim_max = (PROBLEM::time_limit - PROBLEM::time_usage + 999) / 1000 + 1;//硬限制 lim.rlim_cur = lim.rlim_max; //软限制 if (setrlimit(RLIMIT_CPU, &lim) < 0) { FM_LOG_WARNING("error setrlimit for RLIMIT_CPU"); exit(JUDGE_CONF::EXIT_SET_LIMIT); } //内存不能在此做限制 //原因忘了,反正是linux的内存分配机制的问题 //所以得在运行时不断累计内存使用量来限制 //堆栈空间限制 getrlimit(RLIMIT_STACK, &lim); int rlim = JUDGE_CONF::STACK_SIZE_LIMIT * JUDGE_CONF::KILO; if (lim.rlim_max <= rlim) { FM_LOG_WARNING("cannot set stack size to higher(%d <= %d)", lim.rlim_max, rlim); } else { lim.rlim_max = rlim; lim.rlim_cur = rlim; if (setrlimit(RLIMIT_STACK, &lim) < 0) { FM_LOG_WARNING("error setrlimit for RLIMIT_STACK"); exit(JUDGE_CONF::EXIT_SET_LIMIT); } } log_close(); //关闭log,防止log造成OLE //输出文件大小限制 lim.rlim_max = PROBLEM::output_limit * JUDGE_CONF::KILO; lim.rlim_cur = lim.rlim_max; if (setrlimit(RLIMIT_FSIZE, &lim) < 0) { perror("setrlimit RLIMIT_FSIZE failed\n"); exit(JUDGE_CONF::EXIT_SET_LIMIT); } }
/* * 输入输出重定向 */ 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."); }
void update_result(oj_solution_t &oj_solution) { char buffer[BUFF_SIZE]; snprintf(buffer, BUFF_SIZE, "%s/%s/result.txt", oj_solution.work_dir, oj_solution.sid); FILE *fp = fopen(buffer, "r"); if (fp == nullptr) { FM_LOG_WARNING("cannot open file %s", buffer); update_system_error(ERROR_READ_FILE, oj_solution); return; } int number = fscanf(fp, "%d %d %d %d", &oj_solution.result, &oj_solution.time_usage, &oj_solution.memory_usage, &oj_solution.test); fclose(fp); if (number < 4) { FM_LOG_WARNING("read result failed!"); update_system_error(ERROR_READ_RESULT, oj_solution); return; } char *p = nullptr; if (oj_solution.result == OJ_CE) { snprintf(buffer, BUFF_SIZE, "%s/%s/stderr_compiler.txt", oj_solution.work_dir, oj_solution.sid); p = buffer; } else if (oj_solution.result == OJ_RE) { snprintf(buffer, BUFF_SIZE, "%s/%s/stderr_executive.txt", oj_solution.work_dir, oj_solution.sid); p = buffer; } else if (oj_solution.result == OJ_SE || oj_solution.result == OJ_RF) { snprintf(buffer, BUFF_SIZE, "%s/%s/error.txt", oj_solution.work_dir, oj_solution.sid); p = buffer; } else if (oj_solution.result == OJ_WA || oj_solution.result == OJ_PE) { snprintf(buffer, BUFF_SIZE, "%s/%s/diff.out", oj_solution.work_dir, oj_solution.sid); p = buffer; } send_multi_result(p, oj_solution); }
void check_pid() { pid_t otherpid; FM_LOG_NOTICE("pid file: %s", PID_FILE); pfh = pidfile_open(PID_FILE, 0644, &otherpid); if (pfh == nullptr) { if (errno == EEXIST) { FM_LOG_FATAL("Daemon already running, pid: %jd", (intmax_t) otherpid); exit(EXIT_FAILURE); } /* If we cannot create pidfile from other reasons, only warn. */ FM_LOG_WARNING("Cannot open or create pidfile"); } }
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; }
/** fmRawPacketSocketReceivePackets * \ingroup intPlatformCommon * * \desc Handles reception of packets by raw packet socket. * * \param[in] args is a pointer to the switch number. * * \return FM_OK if successful. * *****************************************************************************/ void * fmRawPacketSocketReceivePackets(void *args) { fm_thread * thread; fm_int sw; fm_buffer * recvChainHead = NULL; fm_buffer * nextBuffer; struct pollfd rfds; struct msghdr msg; struct iovec iov[UIO_MAXIOV]; struct ifreq ifr; fm_int retval; fm_int availableBuffers; fm_int len; fm_int iov_offset; fm_int iov_count = 0; fm_int maxMtu = 0; fm_int newMtu; fm_status status; char strErrBuf[FM_STRERROR_BUF_SIZE]; errno_t strErrNum; fm_byte rawTS[8]; fm_pktSideBandData sbData; #ifdef ENABLE_TIMESTAMP struct cmsghdr * cmsg; union { struct cmsghdr cm; char control[512]; } control; #endif thread = FM_GET_THREAD_HANDLE(args); sw = *(FM_GET_THREAD_PARAM(fm_int, args)); FM_NOT_USED(thread); /* If logging is disabled, thread won't be used */ FM_LOG_ENTRY(FM_LOG_CAT_SWITCH, "thread = %s, sw = %d\n", thread->name, sw); /* initialize the message header */ FM_CLEAR(msg); msg.msg_name = NULL; /* Optional field */ msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 0; msg.msg_flags = 0; #ifdef ENABLE_TIMESTAMP msg.msg_control = &control; msg.msg_controllen = sizeof(control); #endif /* Setup the name of the interface */ FM_STRNCPY_S(ifr.ifr_name, sizeof(ifr.ifr_name), GET_PLAT_STATE(sw)->ifaceName, sizeof(GET_PLAT_STATE(sw)->ifaceName)); /* Prepare the pollfd struct */ rfds.fd = GET_PLAT_STATE(sw)->rawSocket; rfds.events = POLLIN; rfds.revents = 0; /************************************************** * Loop forever calling packet receive handler. **************************************************/ while (TRUE) { errno = 0; retval = poll(&rfds, 1, FM_FDS_POLL_TIMEOUT_USEC); if (retval == -1) { strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno); if (strErrNum == 0) { FM_LOG_WARNING(FM_LOG_CAT_SWITCH, "ERROR: select failed: %s!\n", strErrBuf); } else { FM_LOG_WARNING(FM_LOG_CAT_SWITCH, "ERROR: select failed: %d!\n", errno); } /* Switch was removed, kill the thread */ if (GET_SWITCH_PTR(sw) == NULL) { break; } continue; } else if (!retval) { /* Switch was removed, kill the thread */ if (GET_SWITCH_PTR(sw) == NULL) { break; } continue; /* timeout */ } /* get the number of available buffers from the buffer manager*/ fmPlatformGetAvailableBuffers(&availableBuffers); if (availableBuffers <= FM_RECV_BUFFER_THRESHOLD) { /* wait for buffer to come back, before dequeueing data */ fmYield(); continue; } if (ioctl(GET_PLAT_STATE(sw)->rawSocket, SIOCGIFMTU, &ifr) == -1) { FM_LOG_WARNING(FM_LOG_CAT_SWITCH, "WARNING: failed to read netdev MTU\n"); continue; } else { newMtu = ifr.ifr_mtu; } /* MTU Size change */ if (newMtu != maxMtu) { if (recvChainHead != NULL) { /* release the existing buffer chain */ status = fmFreeBufferChain(FM_FIRST_FOCALPOINT, recvChainHead); if (status != FM_OK) { FM_LOG_ERROR( FM_LOG_CAT_SWITCH, "Unable to release prior buffer chain, " "status = %d (%s)\n", status, fmErrorMsg(status) ); } recvChainHead = NULL; } /* compute new buffer count */ iov_count = newMtu / FM_BUFFER_SIZE_BYTES; if (newMtu % FM_BUFFER_SIZE_BYTES) { iov_count++; } maxMtu = newMtu; } if (recvChainHead == NULL) { /* allocate a new buffer chain and initialize iovec array */ msg.msg_iovlen = 0; /* 8-Byte Timestamp IOV */ iov[msg.msg_iovlen].iov_base = rawTS; iov[msg.msg_iovlen].iov_len = sizeof(rawTS); msg.msg_iovlen++; for (iov_offset = 0 ; iov_offset < iov_count ; iov_offset++) { do { nextBuffer = fmAllocateBuffer(FM_FIRST_FOCALPOINT); if (nextBuffer == NULL) { /* Wait a little while for buffer to return */ fmDbgGlobalDiagCountIncr(FM_GLOBAL_CTR_RX_OUT_OF_BUFFERS, 1); fmYield(); } } while (nextBuffer == NULL); if (recvChainHead == NULL) { recvChainHead = nextBuffer; nextBuffer->next = NULL; } else { status = fmAddBuffer(recvChainHead, nextBuffer); if (status != FM_OK) { FM_LOG_ERROR( FM_LOG_CAT_SWITCH, "Unable to add buffer %d (%p) to chain %p\n", iov_offset, (void *) nextBuffer, (void *) recvChainHead ); break; } } iov[msg.msg_iovlen].iov_base = nextBuffer->data; iov[msg.msg_iovlen].iov_len = FM_BUFFER_SIZE_BYTES; msg.msg_iovlen++; } } /* now receive from the driver */ len = recvmsg(GET_PLAT_STATE(sw)->rawSocket, &msg, 0); if (len == -1) { continue; } #ifdef ENABLE_TIMESTAMP for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if ( (cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SO_TIMESTAMPING) && (cmsg->cmsg_len == CMSG_LEN(sizeof(struct timespec) * 3)) ) { struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg); /* cmsg has 3 different timestamps. Timestamp we are interested is * located in index 2 */ sbData.ingressTimestamp.seconds = ( (fm_int64)(stamp[2].tv_sec) ); sbData.ingressTimestamp.nanoseconds = ( (fm_int64)(stamp[2].tv_nsec) ); } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "Unknown control message of level %d type %d len %zu received\n", cmsg->cmsg_level, cmsg->cmsg_type, cmsg->cmsg_len); } } #endif /* Remove the timestamp's length to get the length of the actual * packet */ len -= sizeof(rawTS); /* The raw socket does not carry the FCS in either tx or rx, however * the API expects it to be present. Because the API clears the * FCS value before sending the packet event to the application, don't * bother about setting the correct FCS value and just increment the * length. The FCS value is undefined (whatever is in the fm_buffer at * the FCS position). */ len += 4; /* fill in the used buffer sizes */ nextBuffer = recvChainHead; while (nextBuffer != NULL) { if (len > FM_BUFFER_SIZE_BYTES) { nextBuffer->len = FM_BUFFER_SIZE_BYTES; } else { nextBuffer->len = len; } len -= nextBuffer->len; if ( (len <= 0) && (nextBuffer->next != NULL) ) { status = fmFreeBufferChain(FM_FIRST_FOCALPOINT, nextBuffer->next); if (status != FM_OK) { FM_LOG_ERROR( FM_LOG_CAT_SWITCH, "Unable to release unused buffer chain, " "status = %d (%s)\n", status, fmErrorMsg(status) ); } nextBuffer->next = NULL; } nextBuffer = nextBuffer->next; } if (recvChainHead == NULL) { continue; } /* Store the raw timestamp in 64b format */ sbData.rawTimeStamp = ((fm_uint64) (rawTS[0] & 0xFF)) << 56; sbData.rawTimeStamp |= ((fm_uint64) (rawTS[1] & 0xFF)) << 48; sbData.rawTimeStamp |= ((fm_uint64) (rawTS[2] & 0xFF)) << 40; sbData.rawTimeStamp |= ((fm_uint64) (rawTS[3] & 0xFF)) << 32; sbData.rawTimeStamp |= ((fm_uint64) (rawTS[4] & 0xFF)) << 24; sbData.rawTimeStamp |= ((fm_uint64) (rawTS[5] & 0xFF)) << 16; sbData.rawTimeStamp |= ((fm_uint64) (rawTS[6] & 0xFF)) << 8; sbData.rawTimeStamp |= ((fm_uint64) (rawTS[7] & 0xFF)); /* Don't provide an ISL tag pointer, let the API handle the ISL * tag information (included in the fm_buffer chain). */ status = fmPlatformReceiveProcessV2(sw, recvChainHead, NULL, &sbData); if (status != FM_OK) { FM_LOG_ERROR( FM_LOG_CAT_SWITCH, "Returned error status %d " "(%s)\n", status, fmErrorMsg(status) ); } /* Buffer chain has now been consumed */ recvChainHead = NULL; } /* end while (TRUE) */ fmExitThread(thread); return NULL; } /* end fmRawPacketSocketReceivePackets */
/* * #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 } } }
/** fmIsRawPacketSocketDeviceOperational * \ingroup intPlatformCommon * * \desc If raw packet socket was initialized, it verifies that * the underlying network device is operational. * * \param[in] sw refers to the switch number to send packets to. * * \param[out] isRawSocket is a pointer to a variable specifying if raw * socket is used. * * \param[out] mtu is a pointer to a variable storing mtu value of * the raw sockets network device. * * \return TRUE if either raw packet socket was not initialized or * raw packet socket is initialized and the underlying network * device is operational. * \return FALSE if raw packet socket is initialized and the underlying * network device is not operational. * *****************************************************************************/ fm_bool fmIsRawPacketSocketDeviceOperational(fm_int sw, fm_bool *isRawSocket, fm_int * mtu) { fm_switch *switchPtr; char strErrBuf[FM_STRERROR_BUF_SIZE]; errno_t strErrNum; struct ifreq ifr; FM_LOG_ENTRY(FM_LOG_CAT_PLATFORM, "sw=%d\n", sw); switchPtr = GET_SWITCH_PTR(sw); if (isRawSocket != NULL) { *isRawSocket = FM_DISABLED; } if (switchPtr->isRawSocketInitialized == FM_DISABLED) { FM_LOG_EXIT_CUSTOM(FM_LOG_CAT_PLATFORM, TRUE, "No raw packet socket\n"); } FM_STRNCPY_S(ifr.ifr_name, IF_NAMESIZE, GET_PLAT_STATE(sw)->ifaceName, IF_NAMESIZE); if (ioctl(GET_PLAT_STATE(sw)->rawSocket, SIOCGIFFLAGS, &ifr) == -1) { strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno); if (strErrNum == 0) { FM_LOG_FATAL(FM_LOG_CAT_PLATFORM, "Failed to get socket %d flags for device %s: %s\n", GET_PLAT_STATE(sw)->rawSocket, ifr.ifr_name, strErrBuf); } else { FM_LOG_FATAL(FM_LOG_CAT_PLATFORM, "Failed to get socket %d flags for device %s: %d\n", GET_PLAT_STATE(sw)->rawSocket, ifr.ifr_name, errno); } FM_LOG_EXIT_CUSTOM(FM_LOG_CAT_PLATFORM, FALSE, "Not operational\n"); } if ((ifr.ifr_flags & IFF_RUNNING) == 0) { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "Network device %s resources are not allocated.\n", ifr.ifr_name); FM_LOG_EXIT_CUSTOM(FM_LOG_CAT_PLATFORM, FALSE, "Not operational\n"); } if (ioctl(GET_PLAT_STATE(sw)->rawSocket, SIOCGIFMTU, &ifr) == -1) { FM_LOG_WARNING(FM_LOG_CAT_SWITCH, "WARNING: failed to read netdev MTU\n"); FM_LOG_EXIT_CUSTOM(FM_LOG_CAT_PLATFORM, FALSE, "MTU could not be retrieved\n"); } if ( (isRawSocket != NULL) && (mtu != NULL) ) { *isRawSocket = FM_ENABLED; *mtu = ifr.ifr_mtu; } FM_LOG_EXIT_CUSTOM(FM_LOG_CAT_PLATFORM, TRUE, "Operational\n"); } /* fmIsRawPacketSocketDeviceOperational */
/** fmRawPacketSocketSendPackets * \ingroup intPlatformCommon * * \desc When called, iterates through the packet queue and * continues to send packets until either the queue empties. * * \param[in] sw refers to the switch number to send packets to. * * \return FM_OK if successful. * *****************************************************************************/ fm_status fmRawPacketSocketSendPackets(fm_int sw) { fm_status err = FM_OK; fm_switch * switchPtr; fm_packetHandlingState *pktState; fm_packetQueue * txQueue; fm_packetEntry * packet; fm_int32 rc; fm_buffer *sendBuf; struct msghdr msg; struct iovec iov[UIO_MAXIOV]; fm_islTag islTag; fm_uint32 fcs; fm_uint64 rawTS; char strErrBuf[FM_STRERROR_BUF_SIZE]; errno_t strErrNum; struct ifreq ifr; FM_LOG_ENTRY(FM_LOG_CAT_EVENT_PKT_TX, "sw = %d\n", sw); switchPtr = GET_SWITCH_PTR(sw); pktState = GET_PLAT_PKT_STATE(sw); if (GET_PLAT_STATE(sw)->rawSocket <= 0) { FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_TX, "Socket is not initialized.\n"); FM_LOG_EXIT(FM_LOG_CAT_EVENT_PKT_TX, FM_ERR_UNINITIALIZED); } /* initialize the message header */ FM_CLEAR(msg); msg.msg_name = NULL; /* Optional field */ msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 0; msg.msg_flags = 0; FM_STRNCPY_S(ifr.ifr_name, IF_NAMESIZE, GET_PLAT_STATE(sw)->ifaceName, IF_NAMESIZE); txQueue = &pktState->txQueue; fmPacketQueueLock(txQueue); if (ioctl(GET_PLAT_STATE(sw)->rawSocket, SIOCGIFFLAGS, &ifr) == -1) { strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno); if (strErrNum == 0) { FM_LOG_FATAL(FM_LOG_CAT_EVENT_PKT_TX, "Failed to get socket %d flags for device %s: %s\n", GET_PLAT_STATE(sw)->rawSocket, ifr.ifr_name, strErrBuf); } else { FM_LOG_FATAL(FM_LOG_CAT_EVENT_PKT_TX, "Failed to get socket %d flags for device %s: %d\n", GET_PLAT_STATE(sw)->rawSocket, ifr.ifr_name, errno); } switchPtr->transmitterLock = TRUE; err = FM_FAIL; FM_LOG_ABORT(FM_LOG_CAT_EVENT_PKT_TX, err); } if ((ifr.ifr_flags & IFF_RUNNING) == 0) { FM_LOG_WARNING(FM_LOG_CAT_EVENT_PKT_TX, "Network device %s resources are not allocated.\n", ifr.ifr_name); switchPtr->transmitterLock = TRUE; err = FM_FAIL; FM_LOG_ABORT(FM_LOG_CAT_EVENT_PKT_TX, err); } /* Iterate through the packets in the tx queue */ for ( ; txQueue->pullIndex != txQueue->pushIndex ; txQueue->pullIndex = (txQueue->pullIndex + 1) % FM_PACKET_QUEUE_SIZE) { packet = &txQueue->packetQueueList[txQueue->pullIndex]; FM_LOG_DEBUG(FM_LOG_CAT_EVENT_PKT_TX, "sending packet in slot %d, length=%d tag=%d fcs=%08x\n", txQueue->pullIndex, packet->length, packet->suppressVlanTag, packet->fcsVal); msg.msg_iovlen = 0; /* Add the 8 byte timetag iovec. Note that the value is ignored * by the driver as it gets overwritten by the PEP. */ rawTS = 0; iov[msg.msg_iovlen].iov_base = &rawTS; iov[msg.msg_iovlen].iov_len = sizeof(rawTS); msg.msg_iovlen++; if (packet->islTagFormat == FM_ISL_TAG_F56) { /* Add the FTAG (F56) iovec */ islTag.f56.tag[0] = htonl(packet->islTag.f56.tag[0]); islTag.f56.tag[1] = htonl(packet->islTag.f56.tag[1]); iov[msg.msg_iovlen].iov_base = &islTag.f56.tag[0]; iov[msg.msg_iovlen].iov_len = FM_F56_BYTE_LEN; msg.msg_iovlen++; } /* iterate through all buffers */ for ( sendBuf = packet->packet ; sendBuf ; sendBuf = sendBuf->next ) { /* if first buffer ... */ if (sendBuf == packet->packet) { /* Cannot modify the send buffer, since the same buffer can be * used multiple times to send to multiple ports */ /* second iovec is the mac header */ iov[msg.msg_iovlen].iov_base = sendBuf->data; iov[msg.msg_iovlen].iov_len = FM_MAC_HDR_BYTE_LEN; msg.msg_iovlen++; if (packet->islTagFormat == FM_ISL_TAG_F64) { /* Insert the F64 ISL tag */ islTag.f64.tag[0] = htonl(packet->islTag.f64.tag[0]); islTag.f64.tag[1] = htonl(packet->islTag.f64.tag[1]); iov[msg.msg_iovlen].iov_base = &islTag.f64.tag[0]; iov[msg.msg_iovlen].iov_len = FM_F64_BYTE_LEN; msg.msg_iovlen++; } /* Third is the data in the first chain */ if (packet->suppressVlanTag) { iov[msg.msg_iovlen].iov_base = &sendBuf->data[4]; iov[msg.msg_iovlen].iov_len = sendBuf->len-16; msg.msg_iovlen++; } else { iov[msg.msg_iovlen].iov_base = &sendBuf->data[3]; iov[msg.msg_iovlen].iov_len = sendBuf->len-12; msg.msg_iovlen++; } } else { /* The rest of the chain */ iov[msg.msg_iovlen].iov_base = sendBuf->data; iov[msg.msg_iovlen].iov_len = sendBuf->len; msg.msg_iovlen++; } } /* end for (...) */ /* Append user-supplied FCS value to packet. */ if (pktState->sendUserFcs) { fcs = htonl(packet->fcsVal); iov[msg.msg_iovlen].iov_base = &fcs; iov[msg.msg_iovlen].iov_len = sizeof(fcs); msg.msg_iovlen++; } /* now send it to the driver */ errno = 0; rc = sendmsg(GET_PLAT_STATE(sw)->rawSocket, &msg, MSG_DONTWAIT); if (rc == -1) { switchPtr->transmitterLock = TRUE; if (errno != EWOULDBLOCK) { err = FM_FAIL; FM_LOG_DEBUG(FM_LOG_CAT_EVENT_PKT_TX, "rawSocket %d\n", GET_PLAT_STATE(sw)->rawSocket); strErrNum = FM_STRERROR_S(strErrBuf, FM_STRERROR_BUF_SIZE, errno); if (strErrNum == 0) { FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_TX, "sendmsg failed: %s - errno %d\n", strErrBuf, errno); } else { FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_TX, "sendmsg failed - errno %d\n", errno); } } if (errno == EMSGSIZE) { switchPtr->transmitterLock = FALSE; } else { goto ABORT; } } else { FM_LOG_DEBUG(FM_LOG_CAT_EVENT_PKT_TX, "%d bytes were sent\n", rc); switchPtr->transmitterLock = FALSE; fmDbgDiagCountIncr(sw, FM_CTR_TX_PKT_COMPLETE, 1); } /************************************************** * free buffer only when * (1) sending to a single port; * or (2) this is the last packet of multiple * identical packets **************************************************/ if (packet->freePacketBuffer) { /* ignore the error code since it's better to continue */ (void) fmFreeBufferChain(sw, packet->packet); fmDbgGlobalDiagCountIncr(FM_GLOBAL_CTR_TX_BUFFER_FREES, 1); } } ABORT: fmPacketQueueUnlock(txQueue); FM_LOG_EXIT(FM_LOG_CAT_EVENT_PKT_TX, err); } /* end fmRawPacketSocketSendPackets */
/* * 编译源代码 */ 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); } } }
/* fmPlatformLibLoad * \ingroup intPlatform * * \desc Load platform library functions. * * \param[in] sw is the switch number. * * \return FM_OK if successful. * *****************************************************************************/ fm_status fmPlatformLibLoad(fm_int sw) { fm_status status; fm_platformCfgLib *libCfg; fm_platformLib *libFunc; fm_int libHandle; fm_int tempHandle; void * funcAddr; union { fm_platResetSwitchFunc swResetFunc; fm_platI2cWrRdFunc i2cWrRdFunc; fm_platInitSwitchFunc initSwitchFunc; fm_platSelectBusFunc selectBusFunc; fm_platGetPortXcvrState getPortXcvrStateFunc; fm_platSetPortXcvrState setPortXcvrStateFunc; fm_platSetPortLed setPortLedFunc; fm_platEnablePortIntr enablePortIntrFunc; fm_platGetPortIntrPending getPortIntrPendFunc; fm_platDoDebug doDebugFunc; fm_platPostInit PostInitFunc; fm_platSetVrmVoltage SetVrmVoltageFunc; fm_platGetVrmVoltage GetVrmVoltageFunc; void * obj; } alias; if (sw < 0 || sw >= FM_PLAT_NUM_SW) { FM_LOG_EXIT(FM_LOG_CAT_PLATFORM, FM_ERR_INVALID_ARGUMENT); } libCfg = FM_PLAT_GET_LIBS_CFG(sw); libFunc = FM_PLAT_GET_LIB_FUNCS_PTR(sw); /* NOTE: All supports are optional so don't return error unless neccessary */ libHandle = -1; if ( strlen(libCfg->libName) ) { status = fmLoadAndInitDynamicLib(libCfg->libName, FM_PLAT_LIB_INIT_FUNC_NAME, NULL, &tempHandle); libHandle = status ? -1 : tempHandle; } /* Switch reset library support */ if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_RESET_SWITCH_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_RESET_SWITCH_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->ResetSwitch = alias.swResetFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_RESET_SWITCH_FUNC_NAME); } } /* I2C library support */ if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_I2C_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_I2C_RW_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->I2cWriteRead = alias.i2cWrRdFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_I2C_RW_FUNC_NAME); } } /* Debug function */ if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_DEBUG_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_DEBUG_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->DoDebug = alias.doDebugFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_DEBUG_FUNC_NAME); } } /* Transceiver library support */ if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_INIT_SW_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_INIT_SW_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->InitSwitch = alias.initSwitchFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_INIT_SW_FUNC_NAME); } } if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_SEL_BUS_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_SEL_BUS_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->SelectBus = alias.selectBusFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s\n", fmErrorMsg(status), FM_PLAT_SEL_BUS_FUNC_NAME); } } if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_GET_PORT_XCVR_STATE_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_GET_PORT_XCVR_STATE_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->GetPortXcvrState = alias.getPortXcvrStateFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_GET_PORT_XCVR_STATE_FUNC_NAME); } } if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_SET_PORT_XCVR_STATE_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_SET_PORT_XCVR_STATE_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->SetPortXcvrState = alias.setPortXcvrStateFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_SET_PORT_XCVR_STATE_FUNC_NAME); } } /* LED library support */ if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_SET_PORT_LED_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_SET_PORT_LED_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->SetPortLed = alias.setPortLedFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_SET_PORT_LED_FUNC_NAME); } } /* Interrupt library support */ if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_ENABLE_PORT_INTR_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_ENABLE_PORT_INTR_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->EnablePortIntr = alias.enablePortIntrFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_ENABLE_PORT_INTR_FUNC_NAME); } } if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_GET_PORT_INTR_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_GET_PORT_INTR_PEND_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->GetPortIntrPending = alias.getPortIntrPendFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_GET_PORT_INTR_PEND_FUNC_NAME); } } if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_POST_INIT_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_POST_INIT_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->PostInit = alias.PostInitFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_POST_INIT_FUNC_NAME); } } /* VRM set library support */ if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_SET_VRM_VOLTAGE_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_SET_VRM_VOLTAGE_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->SetVrmVoltage = alias.SetVrmVoltageFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_SET_VRM_VOLTAGE_FUNC_NAME); } } /* VRM get library support */ if ( (libHandle >= 0) && !(libCfg->disableFuncIntf & FM_PLAT_DISABLE_GET_VRM_VOLTAGE_FUNC) ) { status = fmGetDynamicLoadSymbol(libHandle, FM_PLAT_GET_VRM_VOLTAGE_FUNC_NAME, &funcAddr); if (status == FM_OK) { alias.obj = funcAddr; libFunc->GetVrmVoltage = alias.GetVrmVoltageFunc; } else { FM_LOG_WARNING(FM_LOG_CAT_PLATFORM, "%s: Unable to load %s.\n", fmErrorMsg(status), FM_PLAT_GET_VRM_VOLTAGE_FUNC_NAME); } } return FM_OK; } /* end fmPlatformLibLoad */
/* * 执行用户提交的程序 */ 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 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; }
/** fmDistributeEvent * \ingroup intSwitch * * \desc distributes events to those processes that have registered * an interest in the particular event. * * \param[in] event points to the event structure. * * \return Nothing. * *****************************************************************************/ void fmDistributeEvent(fm_event *event) { fmCaptureLock(&fmRootApi->localDeliveryLock, FM_WAIT_FOREVER); { /************************************************** * We want to have a consistent snapshot of the * local delivery list, but we don't want to hold * the lock while we deliver all the events, so we * briefly grab the lock and copy the list into a * C99 variable-size array. **************************************************/ fm_uint count = fmRootApi->localDeliveryCount; fm_localDelivery delivery[count]; fm_dlist_node * node; fm_uint i; fm_uint pktDeliveryCount = 0; fm_eventPktRecv *rcvPktEvent = NULL; fm_status status; fm_buffer *buffer; node = FM_DLL_GET_FIRST( (&fmRootApi->localDeliveryThreads), head ); for (i = 0 ; (node != NULL) && (i < count) ; i++) { delivery[i] = *(fm_localDelivery *) node->data; if ( (delivery[i].mask & (FM_EVENT_PKT_RECV | FM_EVENT_SFLOW_PKT_RECV)) & event->type ) { /* Found thread we need to deliver packet to. */ pktDeliveryCount++; } node = FM_DLL_GET_NEXT(node, next); } /************************************************** * If the event is packet receive but no one has * registered for the event, free the associated * packet buffer and return. **************************************************/ if ( ( (event->type == FM_EVENT_PKT_RECV) || (event->type == FM_EVENT_SFLOW_PKT_RECV) ) && (pktDeliveryCount == 0) ) { rcvPktEvent = &event->info.fpPktEvent; if (enableFramePriority) { status = fmFreeBufferQueueNode(event->sw, rcvPktEvent); if (status != FM_OK) { FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_RX, "Freeing Buffer queue node from the queue failed" "status = %d (%s) \n", status, fmErrorMsg(status)); } } fmFreeBufferChain(event->sw, rcvPktEvent->pkt); fmDbgDiagCountIncr(event->sw, FM_CTR_RX_API_PKT_DROPS, 1); fmReleaseLock(&fmRootApi->localDeliveryLock); return; } /* valid actually found */ count = i; fmReleaseLock(&fmRootApi->localDeliveryLock); /************************************************** * Now we do the actual delivery **************************************************/ for (i = 0 ; i < count ; i++) { fm_event *localEvent = NULL; fm_uint64 nanos = MIN_WAIT_NANOS; fm_status err = FM_FAIL; fm_uint32 numUpdates; if ( (delivery[i].mask & event->type) == 0 ) { continue; } /************************************************** * Always use high priority for the locally dispatched * events, because DistributeEvent is only called from * a single thread (the global event handler), and if * we allocated both low and high priority events here, * we could get priority inversion. **************************************************/ while (localEvent == NULL) { localEvent = fmAllocateEvent(event->sw, event->eventID, event->type, FM_EVENT_PRIORITY_HIGH); if (localEvent == NULL) { DELAY_NANOS(nanos); nanos *= 2; if (nanos > MAX_WAIT_NANOS) { nanos = MAX_WAIT_NANOS; FM_LOG_WARNING(FM_LOG_CAT_EVENT, "Waiting to allocate event of type %d " "for switch %d\n", event->type, event->sw); } } } if (event->type == FM_EVENT_TABLE_UPDATE) { /************************************************** * Because the updates field is a pointer to memory * that has been "secretly" allocated after the event, * rather than just being part of the union, we have * to handle it specially. **************************************************/ numUpdates = event->info.fpUpdateEvent.numUpdates; localEvent->info.fpUpdateEvent.numUpdates = numUpdates; FM_MEMCPY_S( localEvent->info.fpUpdateEvent.updates, numUpdates * sizeof(fm_eventTableUpdate), event->info.fpUpdateEvent.updates, numUpdates * sizeof(fm_eventTableUpdate) ); } else if (event->type == FM_EVENT_PURGE_SCAN_COMPLETE) { localEvent->info.purgeScanComplete = event->info.purgeScanComplete; } else if ( (event->type == FM_EVENT_PKT_RECV) || (event->type == FM_EVENT_SFLOW_PKT_RECV) ) { rcvPktEvent = &event->info.fpPktEvent; /************************************************** * Copy the whole event, including the packet, to * localEvent. If this is not the last registered * client, we will overwrite the packet with a * clone. **************************************************/ localEvent->info = event->info; /************************************************** * If there is more than one remaining process that is * interested in receive packet events, clone the * receive buffer for delivery. **************************************************/ if (pktDeliveryCount-- > 1) { if (enableFramePriority) { FM_LOG_ERROR(FM_LOG_CAT_EVENT, "Prioritization is supported only for the" "first registered process. Subsequent " "processes follow normal buffer allocation" " without prioritization.\n"); } localEvent->info.fpPktEvent.pkt = fmDuplicateBufferChain(event->sw, rcvPktEvent->pkt); if (localEvent->info.fpPktEvent.pkt == NULL) { /************************************************** * Couldn't copy the packet. Free the event so that * it is not lost and continue the loop. **************************************************/ fmReleaseEvent(localEvent); fmDbgDiagCountIncr(event->sw, FM_CTR_RX_API_PKT_DROPS, 1); continue; } } if (enableFramePriority) { buffer = ((fm_buffer *)(localEvent->info.fpPktEvent.pkt)); buffer->recvEvent = localEvent; } } else { /************************************************** * Otherwise, we can just copy the whole union * without worrying what type it is. **************************************************/ localEvent->info = event->info; } /************************************************** * Now try to send the event to the local dispatch * thread, using exponential backoff if the event * queue is full. **************************************************/ nanos = MIN_WAIT_NANOS; while (err != FM_OK) { err = fmSendThreadEvent(delivery[i].thread, localEvent); if (err != FM_OK) { DELAY_NANOS(nanos); nanos *= 2; if (nanos > MAX_WAIT_NANOS) { nanos = MAX_WAIT_NANOS; } } /* end if (err != FM_OK) */ } /* end while (err != FM_OK) */ } /* end for (i = 0 ; i < count ; i++) */ } /* end (local scope) */ } /* end fmDistributeEvent */
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."); } } }
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; }
void compile_spj(const char *source, char *target) { int status = execute_cmd("g++ -lm -static -w -std=gnu++17 -O4 -o %s %s", target, source); if (status == -1) { FM_LOG_WARNING("compile spj failed: %s", strerror(errno)); } }
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)); } } } }
/** fmDuplicateBufferChain * \ingroup buffer * * \desc Duplicate a buffer chain by allocating buffers and copying * the contents from the source buffer(s) into the new * buffer(s). * * \param[in] sw is not used. This is a legacy argument for backward * compatibility with existing applications. * * \param[in] srcFrame is a pointer to the first ''fm_buffer'' structure * in a chain of buffers which are to be cloned into a new * chain. * * \return Pointer to the first buffer in the new chain, or NULL if * the new chain could not be allocated. * *****************************************************************************/ fm_buffer *fmDuplicateBufferChain(fm_int sw, fm_buffer *srcFrame) { fm_buffer *newChain; fm_buffer *currentSrc; fm_buffer *currentDest; FM_LOG_ENTRY_API(FM_LOG_CAT_BUFFER, "sw=%d srcFrame=%p\n", sw, (void *) srcFrame); newChain = NULL; currentSrc = srcFrame; while (currentSrc != NULL) { if (currentSrc->len > 0) { currentDest = fmAllocateBufferV2(sw, srcFrame->bufferType); if (currentDest == NULL) { FM_LOG_WARNING(FM_LOG_CAT_BUFFER, "fmDuplicateBufferChain unable to allocate " "buffer - cancelling duplication\n"); if (newChain != NULL) { fmFreeBufferChain(sw, newChain); newChain = NULL; } break; } FM_MEMCPY_S(currentDest->data, currentSrc->len, currentSrc->data, currentSrc->len); currentDest->len = currentSrc->len; currentDest->next = NULL; if (newChain == NULL) { newChain = currentDest; } else { fmAddBuffer(newChain, currentDest); } } currentSrc = currentSrc->next; } FM_LOG_EXIT_API_CUSTOM(FM_LOG_CAT_BUFFER, newChain, "newChain=%p\n", (void *) newChain); } /* end fmDuplicateBufferChain */
/** fmGlobalEventHandler * \ingroup intSwitch * * \desc event handler for handling system events * * \param[in] args points to the thread arguments * * \return Nothing. * *****************************************************************************/ void *fmGlobalEventHandler(void *args) { fm_thread * thread; fm_event * event; fm_status err = FM_OK; fm_eventPort * portEvent = NULL; fm_eventTableUpdateBurst *updateEvent; fm_int physPort; fm_int logicalPort; fm_eventPktRecv * rcvPktEvent; fm_eventSwitchInserted * insertEvent; fm_eventSwitchRemoved * removeEvent; fm_int sw = 0; fm_bool discardEvent; fm_port * portPtr = NULL; fm_bool switchIsProtected; fm_switch * switchPtr; fm_int mode; fm_int info[8]; fm_int state; fm_int numLanes; fm_uint32 i; fm_bool isPhysicalSwitch; fm_switchEventHandler eventHandler; fm_bool distributeEvent; fm_eventTableUpdate * fpUpdateEvent; /* grab arguments */ thread = FM_GET_THREAD_HANDLE(args); /* wait for initialization to finish before processing events */ fmCaptureSemaphore(&fmRootApi->startGlobalEventHandler, FM_WAIT_FOREVER); enableFramePriority = GET_PROPERTY()->priorityBufQueues; while (1) { /* wait forever for an event */ err = fmGetThreadEvent(thread, &event, FM_WAIT_FOREVER); if (err == FM_ERR_NO_EVENTS_AVAILABLE) { /* A timeout occurred - should never happen. */ continue; } if (event == NULL) { /* NULL event should never happen. */ continue; } sw = event->sw; discardEvent = FALSE; switchIsProtected = FALSE; switchPtr = NULL; if (sw < 0 || sw >= fmRootPlatform->cfg.numSwitches) { discardEvent = TRUE; switchIsProtected = FALSE; } else if ( SWITCH_LOCK_EXISTS(sw) ) { if ( ( err = PROTECT_SWITCH(sw) ) != FM_OK ) { discardEvent = TRUE; switchIsProtected = FALSE; } else { switchIsProtected = TRUE; switchPtr = fmRootApi->fmSwitchStateTable[sw]; if (!fmRootApi->fmSwitchStateTable[sw]) { if ((event->type != FM_EVENT_SWITCH_REMOVED) && (event->type != FM_EVENT_SWITCH_INSERTED) ) { discardEvent = TRUE; } } else if (fmRootApi->fmSwitchStateTable[sw]->state != FM_SWITCH_STATE_UP) { if ((event->type != FM_EVENT_SWITCH_REMOVED) && (event->type != FM_EVENT_SWITCH_INSERTED) ) { discardEvent = TRUE; } } } } else if (event->type != FM_EVENT_SWITCH_INSERTED) { discardEvent = TRUE; } if (discardEvent) { switch (event->type) { case FM_EVENT_PKT_RECV: case FM_EVENT_SFLOW_PKT_RECV: /* Only dig into the event if the switch is valid */ if ( (sw >= 0) && (sw < fmRootPlatform->cfg.numSwitches) ) { rcvPktEvent = &event->info.fpPktEvent; if (enableFramePriority) { err = fmFreeBufferQueueNode(sw, rcvPktEvent); if (err != FM_OK) { FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_RX, "Freeing Buffer queue node from the queue failed" "status = %d (%s) \n", err, fmErrorMsg(err)); } } fmFreeBufferChain(sw, rcvPktEvent->pkt); fmDbgDiagCountIncr(sw, FM_CTR_RX_API_PKT_DROPS, 1); } break; default: break; } goto FINISHED; } eventHandler = NULL; if (switchPtr != NULL) { /* If the switch state table has an eventHandler pointer, * it overrides the global handler. Call the switch-specific * function to handle the event. This is intended to be used * for switches in a switch aggregate (and potentially * nested switch aggregates inside other switch aggregates?). */ eventHandler = switchPtr->eventHandler; switch (switchPtr->switchModel) { case FM_SWITCH_MODEL_SWAG: isPhysicalSwitch = FALSE; break; default: isPhysicalSwitch = TRUE; break; } } else { /* Only physical switches should ever get here with a NULL pointer * because logical switches such as switch aggregates are always * created by application code before any events related to * the switch are possible. */ isPhysicalSwitch = TRUE; } distributeEvent = FALSE; switch (event->type) { case FM_EVENT_SWITCH_INSERTED: insertEvent = &event->info.fpSwitchInsertedEvent; if (switchIsProtected) { UNPROTECT_SWITCH(sw); switchIsProtected = FALSE; } if (switchPtr == NULL) { if (fmHandleSwitchInserted(sw, insertEvent) != FM_OK) { /* Don't generate an insert event if there error */ goto FINISHED; } } distributeEvent = TRUE; break; case FM_EVENT_SWITCH_REMOVED: removeEvent = &event->info.fpSwitchRemovedEvent; if (switchIsProtected) { UNPROTECT_SWITCH(sw); switchIsProtected = FALSE; } if (switchPtr != NULL) { fmHandleSwitchRemoved(sw, removeEvent); } distributeEvent = TRUE; break; case FM_EVENT_PORT: portEvent = &event->info.fpPortEvent; if (isPhysicalSwitch && portEvent->activeMac) { logicalPort = portEvent->port; if (switchPtr != NULL) { fmMapLogicalPortToPhysical(switchPtr, logicalPort, &physPort); portPtr = switchPtr->portTable[logicalPort]; } else { portPtr = NULL; } if (portPtr == NULL) { FM_LOG_ERROR(FM_LOG_CAT_EVENT_PORT, "Unexpected NULL port pointer for logical" " port %d\n", logicalPort); break; } /* This attribute indicate whether the API should flush * all the addresses on a port down event or not. */ if (GET_PROPERTY()->maFlushOnPortDown) { /* If a link goes down for a non-LAG port, remove any * addresses associated with the port from the MA Table. */ if (portEvent->linkStatus == FM_PORT_STATUS_LINK_DOWN) { if (portPtr->portType != FM_PORT_TYPE_LAG) { err = fmFlushPortAddresses(sw, portEvent->port); if (err != FM_OK) { FM_LOG_WARNING(FM_LOG_CAT_EVENT_PORT, "%s\n", fmErrorMsg(err)); } } } } FM_LOG_DEBUG( FM_LOG_CAT_EVENT_PORT, "Port %s event reported on port %d.\n", (portPtr != NULL ) ? ( (portPtr->linkUp) ? "UP " : "DOWN" ) : "UNKN", portEvent->port ); /* inform LAG module of port state changes */ if (portEvent->linkStatus == FM_PORT_STATUS_LINK_UP) { fmInformLAGPortUp(sw, portEvent->port); /* Inform LBGs of port link state change. */ FM_API_CALL_FAMILY_VOID(switchPtr->InformLBGLinkChange, sw, portEvent->port, FM_PORT_STATUS_LINK_UP); } else if (portEvent->linkStatus == FM_PORT_STATUS_LINK_DOWN) { fmInformLAGPortDown(sw, portEvent->port); /* Inform LBGs of port link state change. */ FM_API_CALL_FAMILY_VOID(switchPtr->InformLBGLinkChange, sw, portEvent->port, FM_PORT_STATUS_LINK_DOWN); } /* now update all the source masks */ fmUpdateSwitchPortMasks(sw); if (switchPtr->UpdateRemoveDownPortsTrigger != NULL) { /**************************************************** * Update the switchExt->removeDownPortsTrigger * used to drop routed/multicast/special delivery * frames which can not be handled by the PORT_CFG_2. * See Bugzilla 11387. ***************************************************/ if (portEvent->linkStatus == FM_PORT_STATUS_LINK_UP) { switchPtr->UpdateRemoveDownPortsTrigger(sw, physPort, FALSE); } else if (portEvent->linkStatus == FM_PORT_STATUS_LINK_DOWN) { if (!portPtr->isPortForceUp) { switchPtr->UpdateRemoveDownPortsTrigger(sw, physPort, TRUE); } } } if (switchPtr->UpdateMirrorGroups != NULL) { /**************************************************** * Enable/Disable mirror groups based on the link * status of the mirror port. * See Bugzilla 11387. ***************************************************/ if (portEvent->linkStatus == FM_PORT_STATUS_LINK_UP) { switchPtr->UpdateMirrorGroups(sw, logicalPort, TRUE); } else if (portEvent->linkStatus == FM_PORT_STATUS_LINK_DOWN) { switchPtr->UpdateMirrorGroups(sw, logicalPort, FALSE); } } /* notify anyone else who needs to know */ if (portPtr && portPtr->NotifyLinkEvent) { err = portPtr->NotifyLinkEvent(sw, portEvent->port); if (err != FM_OK) { FM_LOG_WARNING(FM_LOG_CAT_EVENT_PORT, "%s\n", fmErrorMsg(err)); } } /* Get port state and notify platform */ err = fmGetPortStateV3( sw, portEvent->port, portEvent->mac, 8, &numLanes, &mode, &state, info ); if (err != FM_OK) { FM_LOG_WARNING(FM_LOG_CAT_EVENT_PORT, "fmGetPortState(%d,%u) failed: %s\n", sw, portEvent->port, fmErrorMsg(err)); } fmPlatformNotifyPortState(sw, portEvent->port, portEvent->mac, FALSE, state); if (switchIsProtected) { UNPROTECT_SWITCH(sw); switchIsProtected = FALSE; } } /* end if (isPhysicalSwitch) */ distributeEvent = TRUE; break; case FM_EVENT_PKT_RECV: case FM_EVENT_SFLOW_PKT_RECV: fmDbgDiagCountIncr(sw, FM_CTR_RX_API_PKT_FWD, 1); distributeEvent = TRUE; break; case FM_EVENT_PURGE_SCAN_COMPLETE: distributeEvent = TRUE; break; case FM_EVENT_TABLE_UPDATE: if (switchPtr == NULL) { break; } /* Update diagnostic counters. */ updateEvent = &event->info.fpUpdateEvent; i = 0; while (i < updateEvent->numUpdates) { fpUpdateEvent = &updateEvent->updates[i]; if (fpUpdateEvent->event == FM_EVENT_ENTRY_LEARNED) { /* Make sure the MA Table entry matches the entry * in the update event. */ if (switchPtr->RemoveStaleLearnEvent != NULL && switchPtr->RemoveStaleLearnEvent(sw, updateEvent, i)) { /* The learn event has been removed. * Do not update 'i', since it now contains the * following event (if any). */ fmDbgDiagCountIncr(sw, FM_CTR_MAC_LEARN_DISCARDED, 1); } else { fmDbgDiagCountIncr(sw, FM_CTR_MAC_ALPS_LEARN, 1); i++; } } else { if (fpUpdateEvent->event == FM_EVENT_ENTRY_AGED) { fmDbgDiagCountIncr(sw, FM_CTR_MAC_ALPS_AGE, 1); } i++; } } /* If all updates have been removed, don't distribute the event */ if (updateEvent->numUpdates > 0) { distributeEvent = TRUE; } break; case FM_EVENT_SECURITY: case FM_EVENT_FRAME: case FM_EVENT_SOFTWARE: case FM_EVENT_PARITY_ERROR: case FM_EVENT_FIBM_THRESHOLD: case FM_EVENT_CRM: case FM_EVENT_ARP: case FM_EVENT_EGRESS_TIMESTAMP: case FM_EVENT_PLATFORM: case FM_EVENT_LOGICAL_PORT: distributeEvent = TRUE; break; default: FM_LOG_WARNING(FM_LOG_CAT_EVENT_PORT, "Received unknown event %d\n", event->type); break; } /* end switch (event->type) */ if (distributeEvent) { if (switchIsProtected) { UNPROTECT_SWITCH(sw); switchIsProtected = FALSE; } if (eventHandler != NULL) { if (enableFramePriority && ( (event->type == FM_EVENT_PKT_RECV) || (event->type == FM_EVENT_SFLOW_PKT_RECV) ) ) { rcvPktEvent = &event->info.fpPktEvent; err = fmFreeBufferQueueNode(sw, rcvPktEvent); if (err != FM_OK) { FM_LOG_ERROR(FM_LOG_CAT_EVENT_PKT_RX, "Freeing Buffer queue node from the queue failed" "status = %d (%s) \n", err, fmErrorMsg(err)); } } eventHandler(event); } else { fmDistributeEvent(event); } } FINISHED: fmReleaseEvent(event); /* release the switch lock if any is held */ if (switchIsProtected) { UNPROTECT_SWITCH(sw); } } /* end while (1) */ fmExitThread(thread); return NULL; } /* end fmGlobalEventHandler */