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 readErrTask = new AsyncReader(dockerShellProcess.StandardError, settings.OutputLimit).GetDataAsync(); var readOutTask = new AsyncReader(dockerShellProcess.StandardOutput, 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 (!isFinished) { log.Warn($"Не хватило времени ({ms} ms) на работу Docker в папке {dir.FullName}"); unsuccessfulResult = new RunningResults(Verdict.TimeLimit); } 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 и написал: {readOutTask.Result}"); } if (!dockerShellProcess.HasExited) { GracefullyShutdownDocker(dockerShellProcess, name, settings); } if (unsuccessfulResult != null) { return(unsuccessfulResult); } if (dockerShellProcess.ExitCode != 0) { log.Info($"Упал в папке {dir.FullName}"); log.Warn($"Docker написал в stderr:\n{readErrTask.Result}"); return(new RunningResults(Verdict.SandboxError, error: readErrTask.Result)); } return(new RunningResults(Verdict.Ok, output: readOutTask.Result, error: readErrTask.Result)); } }
public static RunningResults Run(CommandRunnerSubmission submission, DockerSandboxRunnerSettings settings, string submissionDirectory) { log.Info($"Запускаю проверку решения {submission.Id}"); var dir = new DirectoryInfo(submissionDirectory); try { Utils.UnpackZip(submission.ZipFileData, dir.FullName); } catch (Exception ex) { log.Error("Не могу распаковать решение", ex); return(new RunningResults(submission.Id, Verdict.SandboxError, error: ex.ToString())); } log.Info($"Запускаю Docker для решения {submission.Id} в папке {dir.FullName}"); return(RunDocker(settings, dir)); }
private static string BuildDockerCommand(DockerSandboxRunnerSettings settings, DirectoryInfo dir, Guid name) { var seccompPath = settings.SeccompFileName == null ? null : ConvertToUnixPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "DockerConfig", settings.SeccompFileName)); var parts = new List <string> { "run", $"-v {ConvertToUnixPath(dir.FullName)}:/source", seccompPath == null ? "" : $"--security-opt seccomp={seccompPath}", "--network none", "--restart no", "--rm", $"--name {name}", $"-m {settings.MemoryLimit}b", $"--memory-swap {settings.MemorySwapLimit}b", "--cpus 1", settings.SandBoxName, $"sh -c \"cp -R /source/* /app/ ; {settings.RunCommand}\"" }; return(string.Join(" ", parts)); }
public static RunningResults Run(CommandRunnerSubmission submission, DockerSandboxRunnerSettings settings, string submissionDirectory) { log.Info($"Запускаю проверку решения {submission.Id}"); var dir = new DirectoryInfo(submissionDirectory); try { ZipHelper.UnpackZip(submission.ZipFileData, dir.FullName); } catch (Exception ex) { var message = "Не могу распаковать решение"; log.Error(ex, message); return(new RunningResults(submission.Id, Verdict.SandboxError) { Logs = new[] { message } }); } log.Info($"Запускаю Docker для решения {submission.Id} в папке {dir.FullName}"); return(RunDocker(settings, dir)); }
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)); } }