bool JudgeTask::match() { ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId); logger->logTrace(OJStr("[JudgeTask] start match...")); MatcherPtr matcher = MatcherFactory::create(false, OJStr("")); matcher->run(answerOutputFile_, userOutputFile_); if(matcher->isAccept()) { output_.Result = AppConfig::JudgeCode::Accept; } else if(matcher->isPresentError()) { output_.Result = AppConfig::JudgeCode::PresentError; } else if(matcher->isWrongAnswer()) { output_.Result = AppConfig::JudgeCode::WrongAnswer; } else if(matcher->isSystemError()) { output_.Result = AppConfig::JudgeCode::SystemError; } return matcher->isAccept(); }
namespace CompileArg { const OJInt32_t limitTime = 20000; const OJInt32_t limitMemory = 32*1024*1024; const OJInt32_t javaLimitTime = 20000; const OJInt32_t javaLimitMemory = 128*1024*1024; const OJString gcc = OJStr("gcc %s -o %s -O2 -Wall -lm --static -std=c99 -DONLINE_JUDGE"); const OJString gPlus = OJStr("g++ %s -o %s -O2 -Wall -lm --static -DONLINE_JUDGE"); const OJString java = OJStr("javac -J-Xms32m -J-Xmx256m %s"); }
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 JudgeTask::init(OJInt32_t judgeID) { judgeID_ = judgeID; OJString codeExt = getLanguageExt(Input.Language); OJString exeExt = getExcuterExt(Input.Language); FormatString(codeFile_, OJStr("work/%d/Main.%s"), judgeID_, codeExt.c_str()); FormatString(exeFile_, OJStr("work/%d/Main.%s"), judgeID_, exeExt.c_str()); FormatString(compileFile_, OJStr("work/%d/compile.txt"), judgeID_); FormatString(userOutputFile_, OJStr("work/%d/output.txt"), judgeID_); FileTool::WriteFile(Input.UserCode, codeFile_); }
bool JudgeTask::excute() { ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId); logger->logTrace(OJStr("[JudgeTask] start excute...")); OJString infoBuffer; if(!FileTool::IsFileExist(exeFile_)) { FormatString(infoBuffer, OJStr("[JudgeTask] not found exe file! %s."), exeFile_); logger->logError(infoBuffer); output_.Result = AppConfig::JudgeCode::SystemError; return false; } ExcuterPtr excuter = ExcuterFactory::create(Input.Language); excuter->run(exeFile_, answerInputFile_, userOutputFile_, Input.LimitTime, Input.LimitMemory); if(excuter->isAccept()) { output_.Result = AppConfig::JudgeCode::Accept; } else if(excuter->isSystemError()) { output_.Result = AppConfig::JudgeCode::SystemError; } else if(excuter->isOutputOutOfLimited()) { output_.Result = AppConfig::JudgeCode::OutputLimited; } else if(excuter->isTimeOutOfLimited()) { output_.Result = AppConfig::JudgeCode::TimeLimitExceed; } else if(excuter->isMemoryOutOfLimited()) { output_.Result = AppConfig::JudgeCode::MemoryLimitExceed; } else if(excuter->isRuntimeError()) { output_.Result = AppConfig::JudgeCode::RuntimeError; } output_.RunTime = excuter->getRunTime(); output_.RunMemory = excuter->getRunMemory(); return excuter->isAccept(); }
bool JudgeTask::compile() { ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId); logger->logTrace(OJStr("[JudgeTask] start compile...")); CompilerPtr compiler = CompilerFactory::create(Input.Language); compiler->run(codeFile_, exeFile_, compileFile_); if(compiler->isAccept()) { output_.Result = AppConfig::JudgeCode::Accept; } else if(compiler->isSystemError()) { output_.Result = AppConfig::JudgeCode::SystemError; } else if(compiler->isCompileError()) { output_.Result = AppConfig::JudgeCode::CompileError; std::vector<OJChar_t> buffer; if(FileTool::ReadFile(buffer, compileFile_) && !buffer.empty()) { output_.CompileError = &buffer[0]; } } return compiler->isAccept(); }
bool WindowsUser::createProcess( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { if (!CreateProcessAsUser(tokenHandle_, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation)) { OutputErrorMsg(OJStr("CreateProcessAsUser faild")); return false; } return true; }
bool WindowsUserProcess::createProcess( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { if (!userPtr_) { throw(std::runtime_error("Invalid windows user !")); } lpStartupInfo->lpDesktop = OJStr("winsta0\\default");//设置交互桌面 return userPtr_->createProcess( lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); }
namespace CompileArg { const OJInt32_t limitTime = 20000; const OJInt32_t limitMemory = 128*1024*1024; const OJString cmd = OJStr("gcc %s -o %s -O2 -Wall -lm --static -std=c99 -DONLINE_JUDGE"); }
bool SetCurPath(const OJString & path) { bool ret = !!::SetCurrentDirectory(path.c_str()); DEBUG_MSG_VS(OJStr("Current Work Directory: %s"), getCurPath().c_str()); return ret; }
//获得文件扩展名 OJString getLanguageExt(OJInt32_t language) { if(language == AppConfig::Language::C) { return OJStr("c"); } else if(language == AppConfig::Language::Cxx) { return OJStr("cpp"); } else if(language == AppConfig::Language::Java) { return OJStr("java"); } return OJStr("unknown"); }
bool WindowsUser::setPrivilege( LPCTSTR lpszPrivilege, // name of privilege to enable/disable BOOL bEnablePrivilege // to enable or disable privilege ) { TOKEN_PRIVILEGES tp; LUID luid; if ( !LookupPrivilegeValue( NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid ) ) // receives LUID of privilege { OutputErrorMsg(OJStr("LookupPrivilegeValue error ")); return false; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if (bEnablePrivilege) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if ( !AdjustTokenPrivileges( tokenHandle_, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { OutputErrorMsg(OJStr("AdjustTokenPrivileges failded")); return false; } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { OutputErrorMsg(OJStr("The token does not have the specified privilege. ")); return false; } return true; }
OJString getExcuterExt(OJInt32_t language) { if(language == AppConfig::Language::C) { return OJStr("exe"); } else if(language == AppConfig::Language::Cxx) { return OJStr("exe"); } else if(language == AppConfig::Language::Java) { return OJStr("class"); } return OJStr("unknown"); }
bool CCompiler::run( const OJString & codeFile, const OJString & exeFile, const OJString & compileFile) { OJString cmdLine; FormatString(cmdLine, CompileArg::cmd.c_str(), codeFile.c_str(), exeFile.c_str()); IMUST::WindowsProcess wp(OJStr(""), compileFile); wp.create(cmdLine, CompileArg::limitTime, CompileArg::limitMemory); result_ = wp.getExitCodeEx(); return isAccept(); }
/* 延迟删除文件。 当某子进程尚未完全退出时,他占用的文件再次被打开或删除,都会失败。故作延迟,等待一段时间。 如果文件始终无法删除,将表示该子进程无法退出,这将是一个致命错误,评判线程应当结束。 */ 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; }
void JavaExcuter::run( const OJString & exeFile, const OJString & inputFile, const OJString & outputFile, OJInt32_t limitTime, OJInt32_t limitMemory ) { OJString exePath = FileTool::GetFilePath(exeFile); OJString exeFileName = FileTool::GetFileName(exeFile);//get only name OJString cmdBuffer; FormatString(cmdBuffer, OJStr("java -cp %s %s"), exePath.c_str(), exeFileName.c_str()); ProcessPtr wp = ProcessFactory::create(ProcessType::Excuter, inputFile, outputFile); wp->create(cmdBuffer, limitTime*30, limitMemory*10); result_ = wp->getResult(); runTime_ = wp->getRunTime(); runMemory_ = wp->getRunMemory(); }
bool InitAppConfig() { #define READ_APP_CONFIG(fun, tag, value) \ if(!root->fun(OJStr(tag), value)) \ { \ logger->logError(OJStr("[config] - IMUST::AppConfig::InitAppConfig: read tag faild! ")##OJStr(tag)); \ return false; \ } ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId); logger->logTrace(GetOJString("[config] - IMUST::AppConfig::InitAppConfig")); XmlPtr root = XmlFactory::getXml(GetOJString("RapidXml")); if(!root->load(OJStr("config.xml"))) { logger->logError(OJStr("[config] - load config file faild! ")); return false; } root = root->read(OJStr("AppConfig")); if(!root) { logger->logError(OJStr("[config] - read tag 'AppConfig' faild! ")); return false; } READ_APP_CONFIG(readInt32, "CpuInfo/NumberOfCore", CpuInfo::NumberOfCore); READ_APP_CONFIG(readString, "MySql/Ip", MySql::Ip); READ_APP_CONFIG(readInt32, "MySql/Port", MySql::Port); READ_APP_CONFIG(readString, "MySql/User", MySql::User); READ_APP_CONFIG(readString, "MySql/Password", MySql::Password); READ_APP_CONFIG(readString, "MySql/DBName", MySql::DBName); READ_APP_CONFIG(readBool, "Compiler/HasMsC", Compiler::HasMsC); READ_APP_CONFIG(readBool, "Compiler/HasMsCxx", Compiler::HasMsCxx); READ_APP_CONFIG(readBool, "Compiler/HasGcc", Compiler::HasGcc); READ_APP_CONFIG(readBool, "Compiler/HasGxx", Compiler::HasGxx); READ_APP_CONFIG(readBool, "Compiler/HasPascal", Compiler::HasPascal); READ_APP_CONFIG(readBool, "Compiler/HasJava", Compiler::HasJava); READ_APP_CONFIG(readBool, "Compiler/HasCs", Compiler::HasCs); READ_APP_CONFIG(readBool, "Compiler/HasPython", Compiler::HasPython); READ_APP_CONFIG(readInt32, "JudgeCode/Pending", JudgeCode::Pending); READ_APP_CONFIG(readInt32, "JudgeCode/Rejudge", JudgeCode::Rejudge); READ_APP_CONFIG(readInt32, "JudgeCode/Compiling", JudgeCode::Compiling); READ_APP_CONFIG(readInt32, "JudgeCode/Accept", JudgeCode::Accept); READ_APP_CONFIG(readInt32, "JudgeCode/PresentError", JudgeCode::PresentError); READ_APP_CONFIG(readInt32, "JudgeCode/WrongAnswer", JudgeCode::WrongAnswer); READ_APP_CONFIG(readInt32, "JudgeCode/TimeLimitExceed", JudgeCode::TimeLimitExceed); READ_APP_CONFIG(readInt32, "JudgeCode/MemoryLimitExceed", JudgeCode::MemoryLimitExceed); READ_APP_CONFIG(readInt32, "JudgeCode/OutputLimited", JudgeCode::OutputLimited); READ_APP_CONFIG(readInt32, "JudgeCode/RuntimeError", JudgeCode::RuntimeError); READ_APP_CONFIG(readInt32, "JudgeCode/CompileError", JudgeCode::CompileError); READ_APP_CONFIG(readInt32, "JudgeCode/CompileTimeError", JudgeCode::CompileTimeError); READ_APP_CONFIG(readInt32, "JudgeCode/CompileOK", JudgeCode::CompileOK); READ_APP_CONFIG(readInt32, "JudgeCode/SystemError", JudgeCode::SystemError); READ_APP_CONFIG(readInt32, "JudgeCode/UnknownError", JudgeCode::UnknownError); READ_APP_CONFIG(readString, "Path/TestDataPath", Path::TestDataPath); READ_APP_CONFIG(readBool, "WindowsUser/Enable", WindowsUser::Enable); READ_APP_CONFIG(readString, "WindowsUser/Name", WindowsUser::Name); READ_APP_CONFIG(readString, "WindowsUser/Password", WindowsUser::Password); #undef READ_APP_CONFIG return true; }
Thread::~Thread() { delete threadProxy_; WatchTool::WatchCount(OJStr("core/numThread"), NumThread, -1); }
namespace WindowsUser { bool Enable = true; OJString Name = OJStr("acmer"); OJString Password = OJStr("imustacm"); }
void Thread::start_thread() { threadProxy_ = new ThreadProxy(fun_.get()); WatchTool::WatchCount(OJStr("core/numThread"), NumThread, +1); }
bool WindowsUser::login(const OJString & userName, const OJString & domain, const OJString & password) { assert(tokenHandle_==NULL && "wrong call!"); // Log the client on to the local computer. if (!LogonUser( userName.c_str(), domain.c_str(), password.c_str(), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &tokenHandle_) ) { tokenHandle_ = NULL; OutputErrorMsg(OJStr("LogonUser failed ")); return false; } // Save a handle to the caller's current window station. HWINSTA hwinstaSave = GetProcessWindowStation(); if (hwinstaSave == NULL) { OutputErrorMsg(OJStr("GetProcessWindowStation failed ")); return false; } // Get a handle to the interactive window station. winstaHandle_ = OpenWindowStation( OJStr("winsta0"), // the interactive window station FALSE, // handle is not inheritable READ_CONTROL | WRITE_DAC); // rights to read/write the DACL if (winstaHandle_ == NULL) { OutputErrorMsg(OJStr("OpenWindowStation failed!")); return false; } // To get the correct default desktop, set the caller's // window station to the interactive window station. if (!SetProcessWindowStation(winstaHandle_)) { OutputErrorMsg(OJStr("SetProcessWindowStation 1 failed ")); return false; } // Get a handle to the interactive desktop. deskHandle_ = OpenDesktop( OJStr("default"), // the interactive window station 0, // no interaction with other desktop processes FALSE, // handle is not inheritable READ_CONTROL | // request the rights to read and write the DACL WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS); // Restore the caller's window station. if (!SetProcessWindowStation(hwinstaSave)) { OutputErrorMsg(OJStr("SetProcessWindowStation 2 failed ")); return false; } if (deskHandle_ == NULL) { OutputErrorMsg(OJStr("OpenDesktop failed")); return false; } // Get the SID for the client's logon session. if (!getLogonSID(tokenHandle_, &pSid_)) { OutputErrorMsg(OJStr("GetLogonSID failed ")); return false; } // Allow logon SID full access to interactive window station. if (! addAceToWindowStation(winstaHandle_, pSid_) ) { OutputErrorMsg(OJStr("AddAceToWindowStation failed ")); return false; } // Allow logon SID full access to interactive desktop. if (! addAceToDesktop(deskHandle_, pSid_) ) { OutputErrorMsg(OJStr("AddAceToDesktop failed ")); return false; } // Impersonate client to ensure access to executable file. if (! ImpersonateLoggedOnUser(tokenHandle_) ) { OutputErrorMsg(OJStr("ImpersonateLoggedOnUser failed ")); return false; } return true; }
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; }
OJInt32_t WindowsProcess::create(const OJString &cmd, const OJInt32_t timeLimit, const OJInt32_t memoryLimit, bool startImmediately) { ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId); { logger->logTraceX(OJStr("[process] - create - CMD='%s' T=%dms, M=%dbytes"), cmd.c_str(), timeLimit, memoryLimit); } if(!createInputFile()) { logger->logError(OJStr("[process] - create - can't creat inputFile")); return -1; } if(!createOutputFile()) { logger->logError(OJStr("[process] - create - can't creat outputFile")); return -1; } if (!jobHandle_.create(useToExcuter_)) { logger->logError(OJStr("[process] - create - can't creat job")); return -1; } if (!jobHandle_.setLimit(timeLimit, memoryLimit)) { logger->logError(OJStr("[process] - create - set job limit failed")); return -1; } OJChar_t cmdline[1024]; wcscpy_s(cmdline, cmd.c_str()); STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); si.cb = sizeof(si); si.wShowWindow = SW_HIDE;//隐藏窗口 si.hStdInput = inputFileHandle_; si.hStdOutput = si.hStdError = outputFileHandle_; si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; //使用handel项和wShowWindow项。 DWORD createFlag = CREATE_SUSPENDED | CREATE_NO_WINDOW | CREATE_BREAKAWAY_FROM_JOB; bool res = createProcess( NULL, // No module name (use command line). cmdline, // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. TRUE, // Set handle inheritance to ... createFlag, // creation flags. NULL, // Use parent 's environment block. NULL, // Use parent 's starting directory. &si, // Pointer to STARTUPINFO structure. &pi); // Pointer to PROCESS_INFORMAT\ION structure. if (!res) { logger->logErrorX(OJStr("[process] - can't creat process. last error: %u"), GetLastError()); return -1; } alive_ = true; processHandle_ = pi.hProcess; threadHandle_ = pi.hThread; if(startImmediately) return start(); return 1; }
namespace Statement { const OJString TestSql = OJStr("update solution set result = 4"); const OJString SelectSolution2 = OJStr("SELECT solution_id, problem_id, user_id, language ") OJStr("FROM `solution` WHERE result=%d or result=%d and solution_id>1904 limit 5"); const OJString SelectProblem1 = OJStr("SELECT time_limit, memory_limit ") OJStr("FROM problem WHERE problem_id =%d"); const OJString SelectCode1 = OJStr("SELECT `source` FROM `source_code` WHERE `solution_id`=%d"); const OJString SelectCustomInput1 = OJStr("SELECT `input_text` from custominput WHERE `solution_id`=%d"); const OJString UpdateSolutionCompiling2 = OJStr("UPDATE `solution` SET `result`=%d, `judgetime`=NOW() ") OJStr("WHERE `solution_id` = %d"); const OJString UpdateSolutionResult5 = OJStr("UPDATE `solution` SET `result`=%d, ") OJStr("`time`=%d, `memory`=%d, `judgetime`=NOW(), `pass_rate`=%f ") OJStr("WHERE `solution_id` = %d"); const OJString DeleteCompile1 = OJStr("DELETE FROM `compileinfo` WHERE `solution_id`=%d"); const OJString InsertCompile2 = OJStr("INSERT INTO `compileinfo`(solution_id, error)VALUES(%d, \"%s\")"); const OJString DeleteRuntime1 = OJStr("DELETE FROM `runtimeinfo` WHERE `solution_id`=%d"); const OJString InsertRuntime2 = OJStr("INSERT INTO `runtimeinfo`(solution_id, error)VALUES(%d, \"%s\")"); const OJString UpdateUserSolved3 = OJStr("UPDATE `users` SET `solved`=") OJStr("(SELECT count(DISTINCT `problem_id`) FROM `solution` ") OJStr("WHERE `user_id`=\'%s\' AND `result`=%d) ") OJStr("WHERE `user_id`=\'%s\'"); const OJString UpdateUserSubmit2 = OJStr("UPDATE `users` SET `submit`=") OJStr("(SELECT count(*) FROM `solution` WHERE `user_id`=\'%s\') ") OJStr("WHERE `user_id`=\'%s\'"); const OJString UpdateProblemAccept3 = OJStr("UPDATE `problem` SET `accepted`=") OJStr("(SELECT count(*) FROM `solution` WHERE `problem_id`=\'%d\' AND `result`=\'%d\') ") OJStr("WHERE `problem_id`=\'%d\'"); const OJString UpdateProblemSubmit2 = OJStr("UPDATE `problem` SET `submit`=") OJStr("(SELECT count(*) FROM `solution` WHERE `problem_id`=\'%d\')") OJStr("WHERE `problem_id`=\'%d\'"); }
void JudgeTask::doRun() { ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId); OJString infoBuffer; FormatString(infoBuffer, OJStr("[JudgeTask] task %d"), Input.SolutionID); logger->logInfo(infoBuffer); //编译 if(!compile()) { return; } //搜索测试数据 OJString path; FormatString(path, OJStr("%s/%d"), AppConfig::Path::TestDataPath.c_str(), Input.ProblemID); DebugMessage(OJStr("[JudgeTask] %d search path: %s"), Input.SolutionID, path.c_str()); //TODO: 根据是否specialJudge,决定搜索.out还是.in文件。 FileTool::FileNameList fileList; FileTool::GetSpecificExtFiles(fileList, path, OJStr(".out"), true); OJUInt32_t testCount = fileList.size(); if(testCount <= 0)//没有测试数据 { output_.Result = AppConfig::JudgeCode::SystemError; FormatString(infoBuffer, OJStr("[JudgeTask] not found test data for solution %d problem %d."), Input.SolutionID, Input.ProblemID); logger->logError(infoBuffer); return; } //测试多组数据 OJUInt32_t accepted = 0; for(OJUInt32_t i=0; i<testCount; ++i) { answerOutputFile_ = fileList[i]; answerInputFile_ = FileTool::RemoveFileExt(answerOutputFile_); answerInputFile_ += OJStr(".in"); DebugMessage(OJStr("[JudgeTask] %d input file: %s"), Input.SolutionID, answerInputFile_.c_str()); DebugMessage(OJStr("[JudgeTask] %d output file: %s"), Input.SolutionID, answerOutputFile_.c_str()); if(!safeRemoveFile(userOutputFile_)) { output_.Result = AppConfig::JudgeCode::SystemError; break; } if(!excute()) { break; } if(!match()) { break; } ++accepted; } output_.PassRate = float(accepted)/testCount; }
bool WindowsJob::setLimit(const OJInt32_t timeLimit, const OJInt32_t memoryLimit) { ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId); //限制时间,单位为100ns。 1ms = 10的6次方ns = 10000 * 100ns。 OJInt64_t limitTime = timeLimit * 10000; // ms->100ns int limitMemory = memoryLimit; //bytes if (limitMemory <= 0) //超出int范围了 limitMemory = 128 * 1024 * 1024; //默认128M //设置基本限制信息 JOBOBJECT_EXTENDED_LIMIT_INFORMATION subProcessLimitRes; ZeroMemory(&subProcessLimitRes, sizeof(subProcessLimitRes)); JOBOBJECT_BASIC_LIMIT_INFORMATION & basicInfo = subProcessLimitRes.BasicLimitInformation; basicInfo.LimitFlags = \ JOB_OBJECT_LIMIT_PRIORITY_CLASS | /*限制job优先级*/ \ JOB_OBJECT_LIMIT_PROCESS_TIME | /*限制job时间*/ \ JOB_OBJECT_LIMIT_PROCESS_MEMORY | /*限制job内存*/ \ JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION | /*遇到异常,让进程直接死掉。*/\ JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | /*进程跟随job一起关闭*/\ JOB_OBJECT_LIMIT_BREAKAWAY_OK; if(useToExcuter_) { basicInfo.LimitFlags |= JOB_OBJECT_LIMIT_ACTIVE_PROCESS; basicInfo.ActiveProcessLimit = 1; } basicInfo.PriorityClass = NORMAL_PRIORITY_CLASS; //优先级为默认 basicInfo.PerProcessUserTimeLimit.QuadPart = limitTime; subProcessLimitRes.ProcessMemoryLimit = limitMemory; if (!setInformation(JobObjectExtendedLimitInformation, &subProcessLimitRes, sizeof(subProcessLimitRes))) { logger->logErrorX(OJStr("[process] - setLimit - can't set job extend info! error:%u"), GetLastError()); return false; } //让完成端口发出时间限制的消息 JOBOBJECT_END_OF_JOB_TIME_INFORMATION timeReport; ZeroMemory(&timeReport, sizeof(timeReport)); timeReport.EndOfJobTimeAction = JOB_OBJECT_POST_AT_END_OF_JOB;//时间到了,通过管道发出信息。 if (!setInformation(JobObjectEndOfJobTimeInformation, &timeReport, sizeof(JOBOBJECT_END_OF_JOB_TIME_INFORMATION))) { logger->logErrorX(OJStr("[process] - setLimit - can't set job end info! error:%u"), GetLastError()); return false; } //UI限制。禁止访问一些资源。 JOBOBJECT_BASIC_UI_RESTRICTIONS subProcessLimitUi; ZeroMemory(&subProcessLimitUi, sizeof(subProcessLimitUi)); subProcessLimitUi.UIRestrictionsClass = JOB_OBJECT_UILIMIT_ALL; if (!setInformation(JobObjectBasicUIRestrictions, &subProcessLimitUi, sizeof(subProcessLimitUi))) { logger->logErrorX(OJStr("[process] - setLimit - can't set job limit info! error:%u"), GetLastError()); return false; } //将作业关联到完成端口,以确定其运行情况,及退出的原因。完成端口可理解为管道,job和应用程序分别位于管道的两端。 //应用程序可以通过管道,查询job的工作状态。 s_mutex_.lock(); ULONG id = ++s_id_; s_mutex_.unlock(); //创建完成端口 iocpHandle_ = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, id, 0); if (NULL == iocpHandle_) { logger->logErrorX(OJStr("[process] - setLimit - create IOCP failed! error:%u"), GetLastError()); return false; } JOBOBJECT_ASSOCIATE_COMPLETION_PORT jobCP; ZeroMemory(&jobCP, sizeof(jobCP)); jobCP.CompletionKey = (PVOID)id; jobCP.CompletionPort = iocpHandle_; if (!setInformation(JobObjectAssociateCompletionPortInformation, &jobCP, sizeof(jobCP))) { logger->logErrorX(OJStr("[process] - setLimit - can't set job CompletionPort info! error:%d"), GetLastError()); return false; } return true; }