feat(submit): 重构提交流程并加强判题端错误处理

- judge_client 在 solution/problem/source 查询失败时记录系统错误并以 OJ_RE 安全退出,避免判题机崩溃或挂起
- submit.php 抽取 submit_error 助手,AJAX 请求返回纯文本错误,提交页改为 AJAX 流程并增强错误提示
- 修复 reinfo 自动刷新脚本在标签页切回前台后未恢复轮询的 bug
This commit is contained in:
2026-07-09 12:03:12 +08:00
parent 418674806b
commit 5a27c07bba
6 changed files with 292 additions and 132 deletions

View File

@@ -1220,6 +1220,17 @@ void addreinfo(int solution_id)
}
}
void add_system_error_info(int solution_id, const char *message)
{
FILE *fp = fopen("error.out", "a");
if (fp != NULL)
{
fprintf(fp, "system:%s\n", message);
fclose(fp);
}
addreinfo(solution_id);
}
void adddiffinfo(int solution_id)
{
@@ -1670,7 +1681,7 @@ int check_mysql_conn(){
#endif
#ifdef _mysql_h
void _get_solution_mysql(int solution_id, char *work_dir, int lang)
bool _get_solution_mysql(int solution_id, char *work_dir, int lang)
{
char sql[BUFFER_SIZE], src_pth[BUFFER_SIZE];
// get the source code
@@ -1678,7 +1689,8 @@ void _get_solution_mysql(int solution_id, char *work_dir, int lang)
MYSQL_ROW row;
sprintf(sql, "SELECT source FROM source_code WHERE solution_id=%d",
solution_id);
mysql_real_query(conn, sql, strlen(sql));
if (mysql_real_query(conn, sql, strlen(sql)))
return false;
res = mysql_store_result(conn);
// create the src file
@@ -1691,16 +1703,23 @@ void _get_solution_mysql(int solution_id, char *work_dir, int lang)
if (DEBUG)
printf("Main=%s", src_pth);
FILE *fp_src = fopen(src_pth, "we");
if (fp_src == NULL) {
mysql_free_result(res);
return false;
}
fprintf(fp_src, "%s", row[0]);
mysql_free_result(res); // free the memory
res = NULL;
row = NULL;
fclose(fp_src);
return true;
}
mysql_free_result(res);
}
return false;
}
#endif
void _get_solution_http(int solution_id, char *work_dir, int lang)
bool _get_solution_http(int solution_id, char *work_dir, int lang)
{
char src_pth[BUFFER_SIZE];
@@ -1716,22 +1735,26 @@ void _get_solution_http(int solution_id, char *work_dir, int lang)
FILE *pout = read_cmd_output(cmd2, solution_id, src_pth, http_baseurl, http_apipath);
pclose(pout);
return access(src_pth, R_OK) == 0;
}
void get_solution(int solution_id, char *work_dir, int lang,int p_id)
bool get_solution(int solution_id, char *work_dir, int lang,int p_id)
{
char src_pth[BUFFER_SIZE];
bool ret = false;
sprintf(src_pth, "Main.%s", lang_ext[lang]);
if (http_judge)
{
_get_solution_http(solution_id, work_dir, lang);
ret = _get_solution_http(solution_id, work_dir, lang);
}
else
{
#ifdef _mysql_h
_get_solution_mysql(solution_id, work_dir, lang);
ret = _get_solution_mysql(solution_id, work_dir, lang);
#endif
}
if (!ret)
return false;
if(lang == LANG_PYTHON ){ // 从源码中搜索python2字样失败的结果非零默认python3,成功的结果为0是python2
py2 = execute_cmd("/bin/grep 'python2' %s/Main.py > /dev/null", work_dir);
execute_cmd("sed -i 's/import.*os//g' %s/%s", work_dir, src_pth);
@@ -1740,6 +1763,7 @@ void get_solution(int solution_id, char *work_dir, int lang,int p_id)
execute_cmd("cp %s/../data/%d/sb3/%d.sb3 %s", work_dir,p_id,solution_id, src_pth);
}
execute_cmd("chown judge %s/%s", work_dir, src_pth);
return access(src_pth, R_OK) == 0;
}
#ifdef _mysql_h
@@ -1804,7 +1828,7 @@ void get_custominput(int solution_id, char *work_dir)
}
#ifdef _mysql_h
void _get_solution_info_mysql(int solution_id, int & p_id, char * user_id,
bool _get_solution_info_mysql(int solution_id, int & p_id, char * user_id,
int & lang,int &cid) {
MYSQL_RES *res;
@@ -1818,7 +1842,8 @@ void _get_solution_info_mysql(int solution_id, int & p_id, char * user_id,
"insert into solution2 select * FROM solution where solution_id=%d",
solution_id);
//printf("%s\n",sql);
mysql_real_query(conn, sql, strlen(sql));
if (mysql_real_query(conn, sql, strlen(sql)))
return false;
sprintf(sql,
"SELECT problem_id, user_id, language,contest_id FROM solution2 where solution_id=%d",
solution_id);
@@ -1831,9 +1856,16 @@ void _get_solution_info_mysql(int solution_id, int & p_id, char * user_id,
solution_id);
}
//printf("%s\n",sql);
mysql_real_query(conn, sql, strlen(sql));
if (mysql_real_query(conn, sql, strlen(sql)))
return false;
res = mysql_store_result(conn);
if (res == NULL)
return false;
row = mysql_fetch_row(res);
if (row == NULL) {
mysql_free_result(res);
return false;
}
p_id = atoi(row[0]);
strcpy(user_id, row[1]);
lang = atoi(row[2]);
@@ -1844,9 +1876,10 @@ void _get_solution_info_mysql(int solution_id, int & p_id, char * user_id,
mysql_free_result(res); // free the memory
res=NULL;
}
return true;
}
#endif
void _get_solution_info_http(int solution_id, int & p_id, char * user_id,
bool _get_solution_info_http(int solution_id, int & p_id, char * user_id,
int & lang,int & cid) {
login();
@@ -1854,26 +1887,29 @@ void _get_solution_info_http(int solution_id, int & p_id, char * user_id,
const char *cmd =
"wget --post-data=\"getsolutioninfo=1&sid=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\"";
FILE *pout = read_cmd_output(cmd, solution_id, http_baseurl, http_apipath);
if(1!=fscanf(pout, "%d", &p_id)) printf("http problem_id read fail...\n");
if(1!=fscanf(pout, "%s", user_id)) printf("http user_id read fail ... \n") ;
if(1!=fscanf(pout, "%d", &lang)) printf("http language read fail ... \n") ;
if(1!=fscanf(pout, "%d", &cid)) printf("http contest_id read fail ... \n") ;
bool ret = true;
if(1!=fscanf(pout, "%d", &p_id)) { printf("http problem_id read fail...\n"); ret = false; }
if(1!=fscanf(pout, "%s", user_id)) { printf("http user_id read fail ... \n") ; ret = false; }
if(1!=fscanf(pout, "%d", &lang)) { printf("http language read fail ... \n") ; ret = false; }
if(1!=fscanf(pout, "%d", &cid)) { printf("http contest_id read fail ... \n") ; ret = false; }
pclose(pout);
return ret;
}
void get_solution_info(int solution_id, int & p_id, char * user_id,
bool get_solution_info(int solution_id, int & p_id, char * user_id,
int & lang,int & cid) {
if (http_judge) {
_get_solution_info_http(solution_id, p_id, user_id, lang,cid);
return _get_solution_info_http(solution_id, p_id, user_id, lang,cid);
} else {
#ifdef _mysql_h
_get_solution_info_mysql(solution_id, p_id, user_id, lang,cid);
return _get_solution_info_mysql(solution_id, p_id, user_id, lang,cid);
#endif
}
return false;
}
#ifdef _mysql_h
void _get_problem_info_mysql(int p_id, double &time_lmt, int &mem_lmt,
bool _get_problem_info_mysql(int p_id, double &time_lmt, int &mem_lmt,
int &spj)
{
// get the problem info from Table:problem
@@ -1883,9 +1919,16 @@ void _get_problem_info_mysql(int p_id, double &time_lmt, int &mem_lmt,
sprintf(sql,
"SELECT time_limit,memory_limit,spj FROM problem where problem_id=%d",
p_id);
mysql_real_query(conn, sql, strlen(sql));
if (mysql_real_query(conn, sql, strlen(sql)))
return false;
res = mysql_store_result(conn);
if (res == NULL)
return false;
row = mysql_fetch_row(res);
if (row == NULL) {
mysql_free_result(res);
return false;
}
time_lmt = atof(row[0]);
mem_lmt = atoi(row[1]);
spj = atoi(row[2]);
@@ -1894,9 +1937,10 @@ void _get_problem_info_mysql(int p_id, double &time_lmt, int &mem_lmt,
mysql_free_result(res); // free the memory
res = NULL;
}
return true;
}
#endif
void _get_problem_info_http(int p_id, double &time_lmt, int &mem_lmt,
bool _get_problem_info_http(int p_id, double &time_lmt, int &mem_lmt,
int &spj)
{
//login();
@@ -1904,27 +1948,32 @@ void _get_problem_info_http(int p_id, double &time_lmt, int &mem_lmt,
const char *cmd =
"wget --post-data=\"getprobleminfo=1&pid=%d\" --load-cookies=cookie --save-cookies=cookie --keep-session-cookies -q -O - \"%s%s\"";
FILE *pout = read_cmd_output(cmd, p_id, http_baseurl, http_apipath);
if(1!=fscanf(pout, "%lf", &time_lmt)) printf("http read time_limit fail...\n");
if(1!=fscanf(pout, "%d", &mem_lmt) ) printf("http read memory_limit fail...\n");
if(1!=fscanf(pout, "%d", &spj) ) printf("http read special judge fail...\n");
bool ret = true;
if(1!=fscanf(pout, "%lf", &time_lmt)) { printf("http read time_limit fail...\n"); ret = false; }
if(1!=fscanf(pout, "%d", &mem_lmt) ) { printf("http read memory_limit fail...\n"); ret = false; }
if(1!=fscanf(pout, "%d", &spj) ) { printf("http read special judge fail...\n"); ret = false; }
pclose(pout);
if(DEBUG) printf("time_lmt:%g\n",time_lmt);
return ret;
}
void get_problem_info(int p_id, double &time_lmt, int &mem_lmt, int &spj)
bool get_problem_info(int p_id, double &time_lmt, int &mem_lmt, int &spj)
{
if (http_judge)
{
_get_problem_info_http(p_id, time_lmt, mem_lmt, spj);
if (!_get_problem_info_http(p_id, time_lmt, mem_lmt, spj))
return false;
}
else
{
#ifdef _mysql_h
_get_problem_info_mysql(p_id, time_lmt, mem_lmt, spj);
if (!_get_problem_info_mysql(p_id, time_lmt, mem_lmt, spj))
return false;
#endif
}
if (time_lmt <= 0)
time_lmt = 1;
return true;
}
char *escape(char s[], char t[])
{
@@ -3455,6 +3504,8 @@ int main(int argc, char **argv)
double time_lmt;
char time_space_table[BUFFER_SIZE*100];
int time_space_index=0;
time_space_table[0]=0;
user_id[0]=0;
umask(0077);
init_parameters(argc, argv, solution_id, runner_id);
@@ -3489,7 +3540,27 @@ int main(int argc, char **argv)
if (http_judge)
if(!system("/bin/ln -s ../cookie ./")) printf("cookie link fail \n");
get_solution_info(solution_id, p_id, user_id, lang,cid);
if (!get_solution_info(solution_id, p_id, user_id, lang,cid)) {
add_system_error_info(solution_id, "solution info not found");
update_solution(solution_id, OJ_RE, 0, 0, 0, 0, 0.0);
#ifdef _mysql_h
if (!http_judge)
mysql_close(conn);
#endif
clean_workdir(work_dir);
exit(0);
}
if (lang < 0 || lang >= (int)(sizeof(lang_ext) / sizeof(lang_ext[0]))) {
add_system_error_info(solution_id, "invalid language id");
update_solution(solution_id, OJ_RE, 0, 0, 0, 0, 0.0);
if(!turbo_mode)update_user(user_id);
#ifdef _mysql_h
if (!http_judge)
mysql_close(conn);
#endif
clean_workdir(work_dir);
exit(0);
}
//get the limit
if (p_id == 0)
@@ -3500,11 +3571,33 @@ int main(int argc, char **argv)
}
else
{
get_problem_info(p_id, time_lmt, mem_lmt, spj);
if (!get_problem_info(p_id, time_lmt, mem_lmt, spj)) {
add_system_error_info(solution_id, "problem info not found");
update_solution(solution_id, OJ_RE, 0, 0, 0, 0, 0.0);
if(!turbo_mode)update_user(user_id);
if(!turbo_mode)update_problem(p_id,cid);
#ifdef _mysql_h
if (!http_judge)
mysql_close(conn);
#endif
clean_workdir(work_dir);
exit(0);
}
}
//copy source file
get_solution(solution_id, work_dir, lang,p_id);
if (!get_solution(solution_id, work_dir, lang,p_id)) {
add_system_error_info(solution_id, "source code not found");
update_solution(solution_id, OJ_RE, 0, 0, 0, 0, 0.0);
if(!turbo_mode)update_user(user_id);
if(!turbo_mode)update_problem(p_id,cid);
#ifdef _mysql_h
if (!http_judge)
mysql_close(conn);
#endif
clean_workdir(work_dir);
exit(0);
}
//java and other VM language are lucky to have the global bonus in judge.conf
if (lang >= LANG_JAVA && lang != LANG_OBJC && lang != LANG_CLANG && lang != LANG_CLANGPP && lang != LANG_GO )
@@ -3581,11 +3674,18 @@ int main(int argc, char **argv)
if(p_id > 0 && namelist_len == -1 ){
write_log("No such dir:%s!\n", fullpath);
char error[BUFFER_SIZE];
snprintf(error, BUFFER_SIZE - 1, "test data directory not found: %s", fullpath);
add_system_error_info(solution_id, error);
update_solution(solution_id, OJ_RE, 0, 0, 0, 0, 0.0);
if(!turbo_mode)update_user(user_id);
if(!turbo_mode)update_problem(p_id,cid);
#ifdef _mysql_h
if (!http_judge)
mysql_close(conn);
#endif
exit(-1);
clean_workdir(work_dir);
exit(0);
}else{
if(DEBUG){
@@ -3702,6 +3802,7 @@ int main(int argc, char **argv)
}
char last_name[BUFFER_SIZE];
last_name[0]=0;
int minus_mark=0;
char path_buf[BUFFER_SIZE];
sprintf(path_buf,"%s/data/%d/",oj_home,p_id);