private void App_OnStartup(object sender, StartupEventArgs e) { _mutex = new Mutex( true, "hjudge_server", out var isSucceed); if (!isSucceed) { MessageBox.Show("本程序已在运行,请勿重复运行", "提示", MessageBoxButton.OK, MessageBoxImage.Error); Environment.Exit(1); } foreach (var i in e.Args) { if (i == "-silent") { Configuration.IsHidden = true; } } try { if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\AppData")) { Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\AppData"); } if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\Files")) { Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\Files"); } if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\Data")) { Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\Data"); } if (Environment.Is64BitProcess) { File.Copy(AppDomain.CurrentDomain.BaseDirectory + "\\x64\\HPSocket4C_U.dll", AppDomain.CurrentDomain.BaseDirectory + "\\HPSocket4C_U.dll", true); } else { File.Copy(AppDomain.CurrentDomain.BaseDirectory + "\\x86\\HPSocket4C_U.dll", AppDomain.CurrentDomain.BaseDirectory + "\\HPSocket4C_U.dll", true); } } catch { MessageBox.Show("程序初始化失败", "提示", MessageBoxButton.OK, MessageBoxImage.Error); Environment.Exit(1); } JudgeHelper.Init(); }
private void Judging(UIElement textBlock, string runExec, string runArgs) { var cur = -1; var noRespondingState = false; var noRespondingTime = new int[_problem.DataSets.Length]; var failToCatchProcessTime = new int[_problem.DataSets.Length]; while (cur < _problem.DataSets.Length - 1) { var failToCatchProcess = false; cur++; if (cur != 0) { Connection.UpdateMainPageState( $"{DateTime.Now:yyyy/MM/dd HH:mm:ss} 评测 #{JudgeResult.JudgeId} 数据点 {cur}/{_problem.DataSets.Length} 完毕,结果:{JudgeResult.Result[cur - 1]}", textBlock); } if ((!string.IsNullOrWhiteSpace(_problem.DataSets[cur].InputFile) && !File.Exists(_problem.DataSets[cur].InputFile)) || !File.Exists(_problem.DataSets[cur].OutputFile)) { JudgeResult.Result[cur] = "Problem Configuration Error"; JudgeResult.Exitcode[cur] = 0; JudgeResult.Score[cur] = 0; JudgeResult.Timeused[cur] = 0; JudgeResult.Memoryused[cur] = 0; } else { if (_problem.InputFileName != "stdin") { if (!string.IsNullOrWhiteSpace(_problem.DataSets[cur].InputFile)) { try { File.Copy(_problem.DataSets[cur].InputFile, _workingdir + "\\" + _problem.InputFileName, true); } catch { Thread.Sleep(2000); try { File.Copy(_problem.DataSets[cur].InputFile, _workingdir + "\\" + _problem.InputFileName, true); } catch { Thread.Sleep(3000); try { File.Copy(_problem.DataSets[cur].InputFile, _workingdir + "\\" + _problem.InputFileName, true); } catch (Exception ex) { JudgeResult.Result[cur] = $"Unknown Error: {ex.Message}"; JudgeResult.Exitcode[cur] = 0; JudgeResult.Score[cur] = 0; JudgeResult.Timeused[cur] = 0; JudgeResult.Memoryused[cur] = 0; continue; } } } } } if (_problem.InputFileName == "stdin") { try { File.Delete(_workingdir + "\\" + _problem.OutputFileName + ".htmp"); } catch { //ignored } } else { try { File.Delete(_workingdir + "\\" + _problem.OutputFileName); } catch { //ignored } } void exit(object sender, EventArgs args) { _isExited = true; } var testId = $"test_hjudge_{_id}"; var execute = new Process { StartInfo = { FileName = string.IsNullOrEmpty(runExec) ? _workingdir + $"\\test_hjudge_{_id}.exe" : runExec, Arguments = string.IsNullOrEmpty(runArgs) ? string.Empty : runArgs, WorkingDirectory = _workingdir, WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, CreateNoWindow = true, UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true }, EnableRaisingEvents = true }; execute.Exited += exit; Task <string> res = null; _isFault = false; _isExited = false; var startCatch = DateTime.Now; JudgeHelper.Subscribe(testId); long lastDt = 0; try { execute.Start(); } catch (Exception ex) { JudgeResult.Result[cur] = $"Unknown Error: {ex.Message}"; JudgeResult.Exitcode[cur] = 0; JudgeResult.Score[cur] = 0; JudgeResult.Timeused[cur] = 0; JudgeResult.Memoryused[cur] = 0; JudgeHelper.Desubscribe(testId); continue; } var inputStream = execute.StandardInput; var outputStream = execute.StandardOutput; while (JudgeHelper.Processes[testId] == null) { if (_isExited || (DateTime.Now - startCatch).TotalSeconds > 10) { failToCatchProcess = true; break; } Thread.Sleep(1); } if (failToCatchProcess) { JudgeHelper.Desubscribe(testId); JudgeResult.Result[cur] = "Unknown Error"; JudgeResult.Score[cur] = 0; failToCatchProcessTime[cur]++; try { execute.Kill(); } catch { //ignored } execute.Close(); if (failToCatchProcessTime[cur] < 3) { cur--; } continue; } var process = JudgeHelper.Processes[testId]; var noChangeTime = DateTime.Now; //Prevent from process suspending / IO block causing no response JudgeHelper.Desubscribe(testId); try { JudgeResult.Timeused[cur] = Math.Max(JudgeResult.Timeused[cur], Convert.ToInt64(process.UserProcessorTime.TotalMilliseconds)); JudgeResult.Memoryused[cur] = Math.Max(JudgeResult.Memoryused[cur], process.PeakWorkingSet64 >> 10); } catch { //ignored } var resume = false; var isNoResponding = false; do { var taskCount = 0; try { while (!_isExited) { taskCount = 0; if (!resume) { resume = true; new Thread(() => { if (_problem.InputFileName == "stdin") { try { res = outputStream.ReadToEndAsync(); inputStream.AutoFlush = true; if (!string.IsNullOrWhiteSpace(_problem.DataSets[cur].InputFile)) { lock (Connection.StdinWriterLock) inputStream.WriteAsync( File.ReadAllText(_problem.DataSets[cur].InputFile, Encoding.Default) + "\0") .ContinueWith(o => { inputStream.Close(); }); } else { inputStream.WriteAsync("\0") .ContinueWith(o => { inputStream.Close(); }); } } catch { //ignored } } else { try { inputStream.Write("\0"); inputStream.Close(); } catch { //ignored } } }).Start(); JudgeHelper.ResumeProcess(process.Id); } JudgeResult.Timeused[cur] = Math.Max(JudgeResult.Timeused[cur], Convert.ToInt64(process.UserProcessorTime.TotalMilliseconds)); if (JudgeResult.Timeused[cur] > _problem.DataSets[cur].TimeLimit) { _isFault = true; _isExited = true; JudgeResult.Result[cur] = "Time Limit Exceeded"; JudgeResult.Score[cur] = 0; JudgeResult.Exitcode[cur] = 0; } taskCount++; JudgeResult.Memoryused[cur] = Math.Max(JudgeResult.Memoryused[cur], process.PeakWorkingSet64 >> 10); if (JudgeResult.Memoryused[cur] > _problem.DataSets[cur].MemoryLimit) { _isFault = true; _isExited = true; JudgeResult.Result[cur] = "Memory Limit Exceeded"; JudgeResult.Score[cur] = 0; JudgeResult.Exitcode[cur] = 0; } taskCount++; if (lastDt == Convert.ToInt64(process.TotalProcessorTime.TotalMilliseconds)) { if ((DateTime.Now - noChangeTime).TotalMilliseconds > _problem.DataSets[cur].TimeLimit * (Connection.CurJudgingCnt - Connection.IntelligentAdditionWorkingThread) * 10) { _isExited = true; isNoResponding = true; break; } try { process.CloseMainWindow(); } catch { //ignored } } else { noChangeTime = DateTime.Now; lastDt = Convert.ToInt64(process.TotalProcessorTime.TotalMilliseconds); } process.Refresh(); } } catch { if (!_isExited) { if (taskCount != 2) { process.Refresh(); } } } } while (!_isExited); try { process.Kill(); } catch { //ignored } try { execute.Kill(); } catch { //ignored } try { JudgeResult.Exitcode[cur] = execute.ExitCode; if (JudgeResult.Exitcode[cur] == 0) { JudgeResult.Exitcode[cur] = process.ExitCode; } if (JudgeResult.Exitcode[cur] != 0 && !_isFault) { JudgeResult.Result[cur] = "Runtime Error"; JudgeResult.Score[cur] = 0; _isFault = true; isNoResponding = false; } } catch { //ignored } JudgeHelper.TerminateProcess(process.Id); if (isNoResponding) { JudgeResult.Result[cur] = "Time Limit Exceeded"; JudgeResult.Score[cur] = 0; noRespondingTime[cur]++; if (!noRespondingState) { lock (Connection.AdditionWorkingThreadLock) { Connection.IntelligentAdditionWorkingThread++; } noRespondingState = true; } process.Close(); execute.Close(); if (noRespondingTime[cur] < 3) { cur--; } continue; } if (_isFault) { process.Close(); execute.Close(); continue; } Thread.Sleep(1); if (_problem.InputFileName != "stdin") { if (!File.Exists(_workingdir + "\\" + _problem.OutputFileName)) { JudgeResult.Result[cur] = "Output File Error"; JudgeResult.Score[cur] = 0; continue; } } else { File.WriteAllText(_workingdir + "\\" + _problem.OutputFileName + ".htmp", res?.Result ?? string.Empty, Encoding.Default); } outputStream.Close(); process.Close(); execute.Close(); Thread.Sleep(1); lock (Connection.ComparingLock) { if (!string.IsNullOrEmpty(_problem.SpecialJudge)) { if (File.Exists(_problem.SpecialJudge)) { try { File.Delete(_workingdir + "\\hjudge_spj_result.dat"); } catch { // ignored } try { var xx = new ProcessStartInfo { ErrorDialog = false, UseShellExecute = true, CreateNoWindow = true, FileName = _problem.SpecialJudge, Arguments = Dn(_problem.DataSets[cur].InputFile) + " " + Dn(_problem.DataSets[cur].OutputFile) + " " + (_problem.InputFileName != "stdin" ? Dn(_workingdir + "\\" + _problem.OutputFileName) : Dn(_workingdir + "\\" + _problem.OutputFileName + ".htmp") ) + " " + Dn(_workingdir + "\\hjudge_spj_result.dat"), WindowStyle = ProcessWindowStyle.Hidden }; var pcs = new Process { StartInfo = xx }; pcs.Start(); if (!pcs.WaitForExit(1000 * 60)) { try { pcs.Kill(); } catch { pcs.Close(); } } Thread.Sleep(1); if (!File.Exists(_workingdir + "\\hjudge_spj_result.dat")) { JudgeResult.Result[cur] = "Special Judge Error"; JudgeResult.Score[cur] = 0; } else { var p = File.ReadAllText(_workingdir + "\\hjudge_spj_result.dat"); p = Regex.Replace(p, @"\s", string.Empty); var gs = Convert.ToSingle(p); JudgeResult.Score[cur] = _problem.DataSets[cur].Score * gs; if (Math.Abs(gs - 1) > 0.00001F) { JudgeResult.Result[cur] = "Wrong Answer"; } else { JudgeResult.Result[cur] = "Correct"; } } } catch { JudgeResult.Result[cur] = "Special Judge Error"; JudgeResult.Score[cur] = 0; } } else { JudgeResult.Result[cur] = "Special Judge Error"; JudgeResult.Score[cur] = 0; } } else { try { var fs1 = new FileStream(_problem.DataSets[cur].OutputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); var fs2 = new FileStream( _problem.InputFileName != "stdin" ? _workingdir + "\\" + _problem.OutputFileName : _workingdir + "\\" + _problem.OutputFileName + ".htmp", FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite); var sr1 = new StreamReader(fs1); var sr2 = new StreamReader(fs2); var iswrong = false; do { string s1; try { s1 = sr1.ReadLine(); } catch { s1 = string.Empty; } string s2; try { s2 = sr2.ReadLine(); } catch { s2 = string.Empty; } if (s1 == null) { s1 = string.Empty; } if (s2 == null) { s2 = string.Empty; } s1 = s1.TrimEnd(' '); s2 = s2.TrimEnd(' '); if (s1 == s2) { continue; } iswrong = true; JudgeResult.Result[cur] = "Wrong Answer"; JudgeResult.Score[cur] = 0; if (Regex.Replace(s1, @"\s", string.Empty) == Regex.Replace(s2, @"\s", string.Empty)) { JudgeResult.Result[cur] = "Presentation Error"; } else { break; } } while (!(sr1.EndOfStream && sr2.EndOfStream)); sr1.Close(); sr2.Close(); fs1.Close(); fs2.Close(); if (iswrong) { continue; } JudgeResult.Result[cur] = "Correct"; JudgeResult.Score[cur] = _problem.DataSets[cur].Score; } catch (Exception ex) { JudgeResult.Result[cur] = $"Unknown Error: {ex.Message}"; JudgeResult.Score[cur] = 0; } } } } Thread.Sleep(1); } if (noRespondingState) { lock (Connection.AdditionWorkingThreadLock) { Connection.IntelligentAdditionWorkingThread--; } } }