Exemplo n.º 1
0
/*
 * 对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);
    //}
}
Exemplo n.º 2
0
/*
 * 解析参数
 */
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";
    }
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
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);
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
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));
        }
    }
}
Exemplo n.º 7
0
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);
}
Exemplo n.º 8
0
/*
 * 程序运行的限制
 * 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);
    }
}
Exemplo n.º 9
0
/*
 * 输入输出重定向
 */
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.");
}
Exemplo n.º 10
0
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);
}
Exemplo n.º 11
0
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");
    }
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
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 */
Exemplo n.º 14
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
        }
    }
}
Exemplo n.º 15
0
/** 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 */
Exemplo n.º 16
0
/** 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 */
Exemplo n.º 17
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);
        }
    }
}
Exemplo n.º 18
0
/* 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 */
Exemplo n.º 19
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);
    }

}
Exemplo n.º 20
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;
}
Exemplo n.º 21
0
/** 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 */
Exemplo n.º 22
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.");
        }
    }
}
Exemplo n.º 23
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;
}
Exemplo n.º 24
0
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));
    }
}
Exemplo n.º 25
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));
            }
        }
    }
}
Exemplo n.º 26
0
/** 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 */
Exemplo n.º 27
0
/** 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 */