Ejemplo n.º 1
0
        private static RunningResults RunDocker(DockerSandboxRunnerSettings settings, DirectoryInfo dir)
        {
            var name          = Guid.NewGuid();
            var dockerCommand = BuildDockerCommand(settings, dir, name);

            log.Info($"Start process command: docker {dockerCommand}");
            using (var dockerShellProcess = BuildShellProcess(dockerCommand))
            {
                var sw = Stopwatch.StartNew();
                dockerShellProcess.Start();
                var utf8StandardErrorReader  = new StreamReader(dockerShellProcess.StandardError.BaseStream, Encoding.UTF8);
                var utf8StandardOutputReader = new StreamReader(dockerShellProcess.StandardOutput.BaseStream, Encoding.UTF8);
                var readErrTask = new AsyncReader(utf8StandardErrorReader, settings.OutputLimit).GetDataAsync();
                var readOutTask = new AsyncReader(utf8StandardOutputReader, settings.OutputLimit).GetDataAsync();
                var isFinished  = Task.WaitAll(new Task[] { readErrTask, readOutTask }, (int)(settings.MaintenanceTimeLimit + settings.TestingTimeLimit).TotalMilliseconds);
                var ms          = sw.ElapsedMilliseconds;

                RunningResults unsuccessfulResult = null;

                if (!dockerShellProcess.HasExited)
                {
                    GracefullyShutdownDocker(dockerShellProcess, name, settings);
                }

                log.Info($"Docker написал в stderr: {readErrTask.Result}");
                log.Info($"Docker написал в stdout: {readOutTask.Result}");

                if (!isFinished)
                {
                    log.Warn($"Не хватило времени ({ms} ms) на работу Docker в папке {dir.FullName}");
                    unsuccessfulResult = new RunningResults(Verdict.TimeLimit, (int)Math.Round(settings.TestingTimeLimit.TotalSeconds));
                }
                else if (readErrTask.Result.Length > settings.OutputLimit || readOutTask.Result.Length > settings.OutputLimit)
                {
                    log.Warn("Программа вывела слишком много");
                    unsuccessfulResult = new RunningResults(Verdict.OutputLimit);
                }
                else
                {
                    log.Info($"Docker закончил работу за {ms} ms");
                }

                if (unsuccessfulResult != null)
                {
                    return(unsuccessfulResult);
                }

                if (dockerShellProcess.ExitCode != 0)
                {
                    log.Warn($"Упал в папке {dir.FullName}");
                    return(new RunningResults(Verdict.SandboxError)
                    {
                        Logs = new[]
                        {
                            $"Exit code: {dockerShellProcess.ExitCode}",
                            $"stdout: {readOutTask.Result}",
                            $"stderr: {readErrTask.Result}"
                        }
                    });
                }

                if (readOutTask.Result == "" && readErrTask.Result == "")                 // Поддержка старого соглашения
                {
                    return new RunningResults(Verdict.Ok)
                           {
                               Logs = new[] { "Чеккер ничего не вывел" }
                           }
                }
                ;

                return(ResultParser.Parse(readOutTask.Result, readErrTask.Result));
            }
        }