diff options
Diffstat (limited to 'judge/jmod_test_line.cpp')
-rw-r--r-- | judge/jmod_test_line.cpp | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/judge/jmod_test_line.cpp b/judge/jmod_test_line.cpp new file mode 100644 index 0000000..33a32b9 --- /dev/null +++ b/judge/jmod_test_line.cpp @@ -0,0 +1,190 @@ +#include<stdio.h> +#include<stdlib.h> +#include<limits.h> +#include<dlfcn.h> +#include<pthread.h> +#include<json/json.h> + +#include<judge_def.h> +#include"judgm_lib.h" +#include"judgm_line.h" +#include"jmod_test.h" +#include"jmod_test_line.h" + +static int line_load_setfile(FILE *set_file,int id,int &timelimit,int &memlimit,double &score){ + int ret; + + json_object *jso; + char buf[JUDGE_SET_FILEMAX]; + + fread(buf,1,sizeof(buf),set_file); + jso = json_tokener_parse(buf); + + timelimit = json_object_get_int(json_object_object_get(jso,"timelimit")); + memlimit = json_object_get_int(json_object_object_get(jso,"memlimit")); + score = json_object_get_double(json_object_array_get_idx(json_object_object_get(jso,"score"),id - 1)); + + json_object_put(jso); + return 0; +} +static void line_sigaction(int sig_num,siginfo_t *sig_info,void *context){ + if(sig_info->si_pid == line_proc->pid && line_proc->status == JUDGE_RUN){ + if(!line_proc->proc_wait(false)){ + line_chk_stop_fn(); + } + } +} +static int line_sig_set(){ + struct sigaction sig; + + sig.sa_sigaction = line_sigaction; + sigemptyset(&sig.sa_mask); + sig.sa_flags = SA_SIGINFO | SA_RESTART; + if(sigaction(SIGCHLD,&sig,NULL)){ + return -1; + } + + return 0; +} +static int line_sig_restore(){ + struct sigaction sig; + + sig.sa_handler = SIG_DFL; + sigemptyset(&sig.sa_mask); + sig.sa_flags = 0; + if(sigaction(SIGCHLD,&sig,NULL)){ + return -1; + } + + return 0; +} +static int line_sig_block(){ + sigset_t mask; + + sigemptyset(&mask); + sigaddset(&mask,SIGCHLD); + if(pthread_sigmask(SIG_BLOCK,&mask,NULL)){ + return -1; + } + + return 0; +} +static int line_sig_unblock(){ + sigset_t mask; + + sigemptyset(&mask); + sigaddset(&mask,SIGCHLD); + if(pthread_sigmask(SIG_UNBLOCK,&mask,NULL)){ + return -1; + } + + return 0; +} +static int line_sig_wait(){ + sigset_t mask; + int num; + + sigfillset(&mask); + sigdelset(&mask,SIGKILL); + sigdelset(&mask,SIGTERM); + sigdelset(&mask,SIGINT); + sigdelset(&mask,SIGCHLD); + sigsuspend(&mask); + + return 0; +} +DLL_PUBLIC int run(judgm_line_info *info){ + int i; + + line_result_data *res_data; + + int set_timelimit; + int set_memlimit; + double set_score; + line_set_data *set_data; + + char main_path[PATH_MAX + 1]; + char exe_path[PATH_MAX + 1]; + + check_init_fn chk_init_fn; + check_run_fn chk_run_fn; + judgm_proc_check_fn chk_proc_fn; + + char data_path[PATH_MAX + 1]; + int chk_status; + + set_data = (line_set_data*)info->set_data; + + res_data = (line_result_data*)info->res_data; + info->res_len = sizeof(line_result_data); + + res_data->id = set_data->id; + res_data->status = JUDGE_ERR; + res_data->score = 0; + res_data->runtime = 0; + res_data->memory = 0; + res_data->err_msg[0] = '\0'; + + if(line_load_setfile(info->set_file,set_data->id,set_timelimit,set_memlimit,set_score)){ + return -1; + } + + snprintf(main_path,sizeof(main_path),"%s/main.cpp",info->code_path); + snprintf(exe_path,sizeof(exe_path),"%s/test",info->run_path); + if(judgm_compile(info->subid,main_path,exe_path,info->lang,false,res_data->err_msg,LINE_ERRMSG_MAXSIZE)){ + res_data->status = JUDGE_CE; + return -1; + } + + chk_init_fn = (check_init_fn)dlsym(info->check_dll,"init"); + chk_run_fn = (check_run_fn)dlsym(info->check_dll,"run"); + chk_proc_fn = (judgm_proc_check_fn)dlsym(info->check_dll,"proc"); + line_chk_stop_fn = (check_stop_fn)dlsym(info->check_dll,"stop"); + line_proc = new judgm_proc(info->judgk_modfd,info->run_path,exe_path,set_timelimit,(set_timelimit * 10 + 5000),set_memlimit,chk_proc_fn); + + snprintf(data_path,sizeof(data_path),"%s/private/%d",info->pro_path,set_data->id); + if(chk_init_fn(info->judgk_modfd,data_path,info->run_path)){ + delete line_proc; + return -1; + } + if(line_sig_set()){ + delete line_proc; + return -1; + } + + if(line_proc->proc_run()){ + delete line_proc; + return -1; + } + chk_run_fn(chk_status,res_data->err_msg); + + line_sig_block(); + if(line_proc->status == JUDGE_RUN){ + line_proc->proc_kill(); + line_sig_wait(); + } + line_sig_unblock(); + + printf("check status %d proc status %d\n",chk_status,line_proc->status); + + if(line_sig_restore()){ + delete line_proc; + return -1; + } + + if(line_proc->status != JUDGE_AC){ + res_data->status = line_proc->status; + }else{ + res_data->status = chk_status; + } + if(res_data->status == JUDGE_AC){ + res_data->score = set_score; + }else{ + res_data->score = 0; + } + res_data->runtime = line_proc->runtime; + res_data->memory = line_proc->memory; + + delete line_proc; + return 0; +} |