void JudgeThread::operator()() { ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId); OJString infoBuffer; FormatString(infoBuffer, OJStr("work/%d"), id_); FileTool::MakeDir(infoBuffer); FormatString(infoBuffer, OJStr("[JudgeThread][%d]start..."), id_); logger->logTrace(infoBuffer); while (!g_sigExit) { IMUST::TaskPtr pTask; //从任务队列取任务 workingTaskMgr_->lock(); if(workingTaskMgr_->hasTask()) { pTask = workingTaskMgr_->popTask(); } workingTaskMgr_->unlock(); if(!pTask)//没有任务 { OJSleep(1000); continue; } pTask->init(id_); if(!pTask->run()) { FormatString(infoBuffer, OJStr("[JudgeThread][%d]System Error!Judge thread will exit!"), id_); logger->logError(infoBuffer); break; } //添加到完成队列 finisheTaskMgr_->lock(); finisheTaskMgr_->addTask(pTask); finisheTaskMgr_->unlock(); OJSleep(10);//防止线程过度繁忙 } FormatString(infoBuffer, OJStr("[JudgeThread][%d]end."), id_); logger->logTrace(infoBuffer); }
void JudgeDBRunThread::operator()() { IMUST::ILogger *logger = IMUST::LoggerFactory::getLogger(IMUST::LoggerId::AppInitLoggerId); logger->logTrace(GetOJString("[DBThread] thread start...")); while(!g_sigExit) { if(!dbm_->run()) { logger->logError(GetOJString("[DBThread] db manager was dead!")); break; } OJSleep(100); } logger->logTrace(GetOJString("[DBThread] thread end.")); }
/* 延迟删除文件。 当某子进程尚未完全退出时,他占用的文件再次被打开或删除,都会失败。故作延迟,等待一段时间。 如果文件始终无法删除,将表示该子进程无法退出,这将是一个致命错误,评判线程应当结束。 */ bool safeRemoveFile(const OJString & file) { OJString infoBuffer; for(OJInt32_t i=0; i<10; ++i)//尝试删除10次 { if(FileTool::RemoveFile(file)) { return true; } OJSleep(1000); FormatString(infoBuffer, OJStr("safeRemoveFile '%s' faild with %d times. code:%d"), file.c_str(), i+1, GetLastError()); LoggerFactory::getLogger(LoggerId::AppInitLoggerId)->logError(infoBuffer); } return false; }
OJInt32_t WindowsProcess::start() { ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId); //加到作业中 if (!jobHandle_.assinProcess(processHandle_)) { logger->logErrorX(OJStr("[process] - can't assign process to job! error:%u"), GetLastError()); kill(); return -1; } //启动线程 ResumeThread(threadHandle_); //关闭不使用的句柄。让进程执行完毕后立即退出。 SAFE_CLOSE_HANDLE_AND_RESET(threadHandle_); SAFE_CLOSE_HANDLE_AND_RESET(inputFileHandle_) SAFE_CLOSE_HANDLE_AND_RESET(outputFileHandle_) result_ = AppConfig::JudgeCode::Accept; DWORD ExecuteResult = -1; ULONG completeKey; LPOVERLAPPED processInfo; bool done = false; while(!done) { if(!jobHandle_.getState(ExecuteResult, completeKey, processInfo)) { DEBUG_MSG(OJStr("get job State faild!")); OJSleep(1); continue; } DWORD dwCode = (DWORD)processInfo; switch (ExecuteResult) { case JOB_OBJECT_MSG_NEW_PROCESS: //DEBUG_MSG_VS(OJStr("[WindowsProcess]new process: %u"), dwCode); break; case JOB_OBJECT_MSG_END_OF_JOB_TIME: //job超时 DEBUG_MSG(OJStr("[WindowsProcess]Job time limit reached")); result_ = AppConfig::JudgeCode::TimeLimitExceed; done = true; break; case JOB_OBJECT_MSG_END_OF_PROCESS_TIME: //线程超时 DEBUG_MSG(OJStr("[WindowsProcess]process time limit reached")); result_ = AppConfig::JudgeCode::TimeLimitExceed; done = true; break; case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: //进程内存超限 DEBUG_MSG(OJStr("[WindowsProcess]Process exceeded memory limit")); result_ = AppConfig::JudgeCode::MemoryLimitExceed; done = true; break; case JOB_OBJECT_MSG_JOB_MEMORY_LIMIT: //job内存超限 { OJInt32_t mem = getRunMemory(); DebugMessage(OJStr("[WindowsProcess]exceeded job memory limit with %dkb"), mem); result_ = AppConfig::JudgeCode::MemoryLimitExceed; done = true; } break; case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT: //超出运行的进程数量 DEBUG_MSG(OJStr("[WindowsProcess]Too many active processes in job")); result_ = AppConfig::JudgeCode::RuntimeError; done = true; break; case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: DEBUG_MSG(OJStr("[WindowsProcess]Job contains no active processes")); done = true; break; case JOB_OBJECT_MSG_EXIT_PROCESS: //进程退出 //DEBUG_MSG_VS(OJStr("[WindowsProcess]Process %u exit."), dwCode); if(::GetProcessId(processHandle_) == dwCode) { done = true; } break; case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: //进程异常结束 DEBUG_MSG(OJStr("[WindowsProcess]Process terminated abnormally")); result_ = AppConfig::JudgeCode::RuntimeError; done = true; break; default: DEBUG_MSG(OJStr("[WindowsProcess]Unknown notification")); result_ = AppConfig::JudgeCode::UnknownError; break; } } { FILETIME ftime, temp; ::GetProcessTimes(processHandle_, &temp, &temp, &temp, &ftime); ULARGE_INTEGER time2; time2.LowPart = ftime.dwLowDateTime; time2.HighPart = ftime.dwHighDateTime; runTime_ = time2.QuadPart / 10000; } { PROCESS_MEMORY_COUNTERS info; ::GetProcessMemoryInfo(processHandle_, &info, sizeof(info)); runMemory_ = info.PeakPagefileUsage; } while(!jobHandle_.terminate())//强制关闭作业 { DEBUG_MSG(OJStr("Terminate job faild!")); OJSleep(10); } alive_ = false;//进程结束 //正常退出。即不是超时等状况。 if(result_ == AppConfig::JudgeCode::Accept) { DWORD code = getExitCode();//获取进程返回值,以判断进程是否执行成功。 if(code != 0) { result_ = AppConfig::JudgeCode::RuntimeError; DEBUG_MSG_VS(OJStr("process exit with code : %u, last error: %u"), code, GetLastError()); } } SAFE_CLOSE_HANDLE_AND_RESET(processHandle_); return 0; }