private async Task <(bool result, string hint)> IsFailedInCompileStageAsync(StateMachineInstanceOutputDto statemachine, CancellationToken token) { if (statemachine.StartedActors.Count() == 1 && statemachine.StartedActors.Last().Name == "CompileActor") { var actor = statemachine.StartedActors.Last(); if (actor.Status == ManagementService.Model.Enums.ActorStatus.Failed) { return(true, string.Join(Environment.NewLine, string.Join("\r\n", actor.Exceptions), null, null)); } else { var runner = await _mgmt.ReadBlobAsObjectAsync <Runner>(actor.Outputs.Single(x => x.Name == "runner.json").Id, token); var stdout = await _mgmt.ReadBlobAsStringAsync(actor.Outputs.Single(x => x.Name == "stdout.txt").Id, token); var stderr = await _mgmt.ReadBlobAsStringAsync(actor.Outputs.Single(x => x.Name == "stderr.txt").Id, token); return(true, string.Join(Environment.NewLine, runner.Error, stdout, stderr)); } } else { return(false, statemachine.StartedActors.First(x => x.Name == "CompileActor").Outputs.Single(x => x.Name.StartsWith("Main")).Id.ToString()); } }
private async Task HandleSingleHackAsync(IEnumerable <ActorInfo> actors, HackStatus hack, JudgeStatus judge, Problem problem, Guid?testCaseId, CancellationToken token) { var sub = new SubJudgeStatus(); var isBadData = false; if (actors.Count(x => x.Name == "CompareActor") == 0) { var rangeValidateActor = actors.FirstOrDefault(x => x.Stage == "ValidateData"); var rangeRunner = rangeValidateActor == null ? null : await _mgmt.ReadBlobAsObjectAsync <Runner>(rangeValidateActor.Outputs.Single(x => x.Name == "runner.json").Id, token); var runActor = actors.FirstOrDefault(x => x.Stage == "GenerateHackeeAnswer"); var runRunner = runActor == null ? null : await _mgmt.ReadBlobAsObjectAsync <Runner>(runActor.Outputs.Single(x => x.Name == "runner.json").Id, token); if (rangeRunner != null && rangeRunner.ExitCode != 0) { isBadData = true; sub.TimeUsedInMs = 0; sub.MemoryUsedInByte = 0; sub.Result = JudgeResult.Accepted; sub.Hint = string.Join(Environment.NewLine, rangeValidateActor.Exceptions) + Environment.NewLine + rangeRunner.Error; } else if (runRunner.IsTimeout) { sub.TimeUsedInMs = problem.TimeLimitationPerCaseInMs; sub.MemoryUsedInByte = runRunner.PeakMemory; sub.Result = JudgeResult.TimeExceeded; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error; } else if (runRunner.ExitCode == 139 || runActor.Exceptions.Any(x => x.Contains("May cause by out of memory")) || runRunner.Error.Contains("std::bad_alloc") || runRunner.PeakMemory > problem.MemoryLimitationPerCaseInByte) { sub.TimeUsedInMs = runRunner.UserTime; sub.MemoryUsedInByte = problem.MemoryLimitationPerCaseInByte; sub.Result = JudgeResult.MemoryExceeded; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error; } else if (runRunner.ExitCode != 0) { sub.TimeUsedInMs = runRunner.UserTime; sub.MemoryUsedInByte = runRunner.PeakMemory; sub.Result = JudgeResult.RuntimeError; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runRunner.Error + Environment.NewLine + $"User process exited with code { runRunner.ExitCode }"; } } else if (actors.Count(x => x.Name == "CompareActor") > 0) { var runners = actors.Where(x => x.Name == "CompareActor").Select(x => x.Outputs.Single(y => y.Name == "runner.json")); var runnerResults = runners.Select(x => _mgmt.ReadBlobAsObjectAsync <Runner>(x.Id, token).Result); var exitCodes = runnerResults.Select(x => x.ExitCode); if (exitCodes.Distinct().Count() > 1) { isBadData = true; } else { var runActor = actors.First(x => x.Stage == "GenerateHackeeAnswer"); var runRunner = await _mgmt.ReadBlobAsObjectAsync <Runner>(runActor.Outputs.Single(x => x.Name == "runner.json").Id, token); var compareActor = actors.Last(x => x.Name == "CompareActor"); var runner = await _mgmt.ReadBlobAsObjectAsync <Runner>(compareActor.Outputs.Single(x => x.Name == "runner.json").Id, token); if (runner.ExitCode < 0 || runner.ExitCode > 2) { sub.TimeUsedInMs = 0; sub.MemoryUsedInByte = 0; sub.Result = JudgeResult.SystemError; sub.Hint = string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runner.Error; } else { var validatorOutput = Encoding.UTF8.GetString((await _mgmt.GetBlobAsync(compareActor.Outputs.Single(x => x.Name == "stdout.txt").Id)).Body); sub.TimeUsedInMs = runRunner.UserTime; sub.MemoryUsedInByte = runRunner.PeakMemory; sub.Result = (JudgeResult)runner.ExitCode; sub.Hint = validatorOutput + Environment.NewLine + string.Join(Environment.NewLine, runActor.Exceptions) + Environment.NewLine + runner.Error; } } } else { isBadData = true; } if (hack == null && actors.Count(x => x.Stage == "GenerateHackeeAnswer") > 0 && testCaseId.HasValue) { var runActor = actors.First(x => x.Stage == "GenerateHackeeAnswer"); var statusId = Guid.Parse(runActor.Tag); var testCase = await _db.TestCases.SingleAsync(x => x.Id == testCaseId.Value, token); var testCases = await _db.TestCases .Where(x => x.ProblemId == problem.Id) .Select(x => x.Id) .ToListAsync(token); var status = await _db.JudgeStatuses .Include(x => x.SubStatuses) .SingleAsync(x => x.Id == statusId, token); sub.StatusId = statusId; sub.TestCaseId = testCaseId.Value; sub.InputBlobId = testCase.InputBlobId; sub.OutputBlobId = testCase.OutputBlobId; sub.SubId = testCases.IndexOf(testCaseId.Value); status.SubStatuses.Add(sub); status.MemoryUsedInByte = status.SubStatuses.Max(x => x.MemoryUsedInByte); status.TimeUsedInMs = status.SubStatuses.Sum(x => x.TimeUsedInMs); status.Result = status.SubStatuses.Max(x => x.Result); _db.SaveChanges(); } if (hack != null) { _db.HackStatuses .Where(x => x.Id == hack.Id) .SetField(x => x.HackeeResult).WithValue(isBadData ? JudgeResult.Accepted : sub.Result) .SetField(x => x.TimeUsedInMs).WithValue(sub.TimeUsedInMs) .SetField(x => x.MemoryUsedInByte).WithValue(sub.MemoryUsedInByte) .SetField(x => x.Result).WithValue(isBadData ? (HackResult.BadData) : (sub.Result == JudgeResult.Accepted ? HackResult.Failed : HackResult.Succeeded)) .SetField(x => x.Hint).WithValue(sub.Hint) .Update(); } }