private void WaitUntilSandboxIsReady(Process sandbox) { var readyLineReadTask = sandbox.StandardOutput.ReadLineAsync(); if (readyLineReadTask.Wait(settings.MaintenanceTimeLimit) && readyLineReadTask.Result == "Ready") { return; } if (!sandbox.HasExited) { throw new SandboxException($"Песочница не ответила «Ready» через {settings.MaintenanceTimeLimit.TotalSeconds} секунд после запуска, убиваю её"); } if (sandbox.ExitCode != 0) { log.Warn($"Песочница не ответила «Ready», а вышла с кодом {sandbox.ExitCode}"); var stderrReader = new AsyncReader(sandbox.StandardError, settings.OutputLimit + 1); var stderrData = stderrReader.GetDataAsync().Result; log.Warn($"Вывод песочницы в stderr:\n{stderrData}"); var result = GetResultForNonZeroExitCode(stderrData, sandbox.ExitCode); throw new SandboxException(result.Error); } throw new SandboxException("Sandbox unexpectedly exited before respond"); }
private void RunSolutionAndWaitUntilSandboxExit(Process sandbox, out string sandboxOutput, out string sandboxError) { sandbox.Refresh(); var startUsedMemory = sandbox.WorkingSet64; var startUsedTime = sandbox.TotalProcessorTime; var startTime = DateTime.Now; sandbox.StandardInput.WriteLine("Run"); sandbox.StandardInput.Flush(); sandbox.StandardInput.WriteLineAsync(submission.Input); var stderrReader = new AsyncReader(sandbox.StandardError, settings.OutputLimit + 1); var stdoutReader = new AsyncReader(sandbox.StandardOutput, settings.OutputLimit + 1); while (!sandbox.HasExited && !CheckIsTimeLimitExceeded(sandbox, startTime, startUsedTime) && !CheckIsMemoryLimitExceeded(sandbox, startUsedMemory) && !CheckIsOutputLimit(stdoutReader) && !CheckIsOutputLimit(stderrReader)) { } if (!hasTimeLimit && !hasMemoryLimit && !hasOutputLimit) { /* Read all data to the end of streams */ sandboxError = stderrReader.GetData(); sandboxOutput = stdoutReader.GetData(); hasOutputLimit = CheckIsOutputLimit(stdoutReader); hasOutputLimit = CheckIsOutputLimit(stderrReader); } else { sandboxError = ""; sandboxOutput = ""; } }
private bool CheckIsOutputLimit(AsyncReader reader) { return(hasOutputLimit = hasOutputLimit || reader.ReadedLength > settings.OutputLimit); }
private bool IsOutputLimit(AsyncReader reader) { return(_hasOutputLimit = _hasOutputLimit || (reader.ReadedLength > OutputLimit)); }
private void RunSandboxer(CompilerResults assembly) { var startInfo = new ProcessStartInfo( "CsSandboxer.exe", string.Format("\"{0}\" {1}", Path.GetFullPath(assembly.PathToAssembly), _submission.Id)) { RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8 }; var sandboxer = Process.Start(startInfo); if (sandboxer == null) { _result.Verdict = Verdict.SandboxError; _result.Error = "Can't start proces"; return; } var stderrReader = new AsyncReader(sandboxer.StandardError, OutputLimit + 1); var readyState = sandboxer.StandardOutput.ReadLineAsync(); if (!readyState.Wait(TimeLimit) || readyState.Result != "Ready") { if (!sandboxer.HasExited) { sandboxer.Kill(); _result.Verdict = Verdict.SandboxError; _result.Error = "Sandbox does not respond"; return; } if (sandboxer.ExitCode != 0) { HandleNonZeroExitCode(stderrReader.GetData(), sandboxer.ExitCode); return; } _result.Verdict = Verdict.SandboxError; _result.Error = "Sandbox exit before respond"; return; } sandboxer.Refresh(); var startUsedMemory = sandboxer.WorkingSet64; var startUsedTime = sandboxer.TotalProcessorTime; var startTime = DateTime.Now; sandboxer.StandardInput.WriteLine("Run"); sandboxer.StandardInput.WriteLineAsync(_submission.Input); var stdoutReader = new AsyncReader(sandboxer.StandardOutput, OutputLimit + 1); while (!sandboxer.HasExited && !IsTimeLimitExpected(sandboxer, startTime, startUsedTime) && !IsMemoryLimitExpected(sandboxer, startUsedMemory) && !IsOutputLimit(stdoutReader) && !IsOutputLimit(stderrReader)) { } if (!sandboxer.HasExited) { sandboxer.Kill(); } if (_hasOutputLimit) { _result.Verdict = Verdict.OutputLimit; return; } if (_hasTimeLimit) { _result.Verdict = Verdict.TimeLimit; return; } if (_hasMemoryLimit) { _result.Verdict = Verdict.MemoryLimit; return; } sandboxer.WaitForExit(); if (sandboxer.ExitCode != 0) { HandleNonZeroExitCode(stderrReader.GetData(), sandboxer.ExitCode); return; } _result.Output = stdoutReader.GetData(); _result.Error = stderrReader.GetData(); }
private bool IsOutputLimit(AsyncReader reader) { return _hasOutputLimit = _hasOutputLimit || (reader.ReadedLength > OutputLimit); }
private void RunSandboxer(CompilerResults assembly) { var startInfo = new ProcessStartInfo( "CsSandboxer.exe", string.Format("\"{0}\" {1}", Path.GetFullPath(assembly.PathToAssembly), _submission.Id)) { RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8 }; var sandboxer = Process.Start(startInfo); if (sandboxer == null) { _result.Verdict = Verdict.SandboxError; _result.Error = "Can't start proces"; return; } var stderrReader = new AsyncReader(sandboxer.StandardError, OutputLimit + 1); var readyState = sandboxer.StandardOutput.ReadLineAsync(); if (!readyState.Wait(TimeLimit) || readyState.Result != "Ready") { if (!sandboxer.HasExited) { sandboxer.Kill(); _result.Verdict = Verdict.SandboxError; _result.Error = "Sandbox does not respond"; return; } if (sandboxer.ExitCode != 0) { HandleNonZeroExitCode(stderrReader.GetData(), sandboxer.ExitCode); return; } _result.Verdict = Verdict.SandboxError; _result.Error = "Sandbox exit before respond"; return; } sandboxer.Refresh(); var startUsedMemory = sandboxer.WorkingSet64; var startUsedTime = sandboxer.TotalProcessorTime; var startTime = DateTime.Now; sandboxer.StandardInput.WriteLine("Run"); sandboxer.StandardInput.WriteLineAsync(_submission.Input); var stdoutReader = new AsyncReader(sandboxer.StandardOutput, OutputLimit + 1); while (!sandboxer.HasExited && !IsTimeLimitExpected(sandboxer, startTime, startUsedTime) && !IsMemoryLimitExpected(sandboxer, startUsedMemory) && !IsOutputLimit(stdoutReader) && !IsOutputLimit(stderrReader)) { } if (!sandboxer.HasExited) sandboxer.Kill(); if (_hasOutputLimit) { _result.Verdict = Verdict.OutputLimit; return; } if (_hasTimeLimit) { _result.Verdict = Verdict.TimeLimit; return; } if (_hasMemoryLimit) { _result.Verdict = Verdict.MemoryLimit; return; } sandboxer.WaitForExit(); if (sandboxer.ExitCode != 0) { HandleNonZeroExitCode(stderrReader.GetData(), sandboxer.ExitCode); return; } _result.Output = stdoutReader.GetData(); _result.Error = stderrReader.GetData(); }
private void RunSandboxer(string args) { var workingDirectory = AppDomain.CurrentDomain.BaseDirectory; log.Info($"Запускаю C#-песочницу с аргументами: {args}\nРабочая директория: {workingDirectory}"); var startInfo = new ProcessStartInfo(Path.Combine(workingDirectory, "CsSandboxer.exe"), args) { RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8 }; startInfo.EnvironmentVariables.Add("InsideSandbox", "true"); Process sandboxer; try { sandboxer = Process.Start(startInfo); } catch (Exception e) { log.Error("Не могу запустить C#-песочницу", e); result.Verdict = Verdict.SandboxError; result.Error = "Can't start process"; return; } if (sandboxer == null) { log.Error("Не могу запустить C#-песочницу. Process.Start() вернул NULL"); result.Verdict = Verdict.SandboxError; result.Error = "Can't start process"; return; } var stderrReader = new AsyncReader(sandboxer.StandardError, settings.OutputLimit + 1); var readyState = sandboxer.StandardOutput.ReadLineAsync(); if (!readyState.Wait(settings.TimeLimit) || readyState.Result != "Ready") { if (!sandboxer.HasExited) { log.Error($"Песочница не завершилась через {settings.TimeLimit.TotalSeconds} секунд, убиваю её"); sandboxer.Kill(); result.Verdict = Verdict.SandboxError; result.Error = "Sandbox does not respond"; return; } if (sandboxer.ExitCode != 0) { HandleNonZeroExitCode(stderrReader.GetData(), sandboxer.ExitCode); return; } result.Verdict = Verdict.SandboxError; result.Error = "Sandbox exit before respond"; return; } sandboxer.Refresh(); var startUsedMemory = sandboxer.WorkingSet64; var startUsedTime = sandboxer.TotalProcessorTime; var startTime = DateTime.Now; sandboxer.StandardInput.WriteLine("Run"); sandboxer.StandardInput.WriteLineAsync(submission.Input); var stdoutReader = new AsyncReader(sandboxer.StandardOutput, settings.OutputLimit + 1); while (!sandboxer.HasExited && !IsTimeLimitExpected(sandboxer, startTime, startUsedTime) && !IsMemoryLimitExpected(sandboxer, startUsedMemory) && !IsOutputLimit(stdoutReader) && !IsOutputLimit(stderrReader)) { } if (!sandboxer.HasExited) { sandboxer.Kill(); } if (hasOutputLimit) { result.Verdict = Verdict.OutputLimit; return; } if (hasTimeLimit) { log.Error("Программа превысила ограничение по времени"); result.Verdict = Verdict.TimeLimit; return; } if (hasMemoryLimit) { log.Error("Программа превысила ограничение по памяти"); result.Verdict = Verdict.MemoryLimit; return; } sandboxer.WaitForExit(); if (sandboxer.ExitCode != 0) { HandleNonZeroExitCode(stderrReader.GetData(), sandboxer.ExitCode); return; } result.Output = stdoutReader.GetData(); result.Error = stderrReader.GetData(); }
private bool IsOutputLimit(AsyncReader reader) { return hasOutputLimit = hasOutputLimit || (reader.ReadedLength > settings.OutputLimit); }
private void RunSandboxer(string args) { var workingDirectory = AppDomain.CurrentDomain.BaseDirectory; log.Info($"Запускаю C#-песочницу с аргументами: {args}\nРабочая директория: {workingDirectory}"); var startInfo = new ProcessStartInfo(Path.Combine(workingDirectory, "CsSandboxer.exe"), args) { RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8 }; startInfo.EnvironmentVariables.Add("InsideSandbox", "true"); Process sandboxer; try { sandboxer = Process.Start(startInfo); } catch (Exception e) { log.Error("Не могу запустить C#-песочницу", e); result.Verdict = Verdict.SandboxError; result.Error = "Can't start process"; return; } if (sandboxer == null) { log.Error("Не могу запустить C#-песочницу. Process.Start() вернул NULL"); result.Verdict = Verdict.SandboxError; result.Error = "Can't start process"; return; } var stderrReader = new AsyncReader(sandboxer.StandardError, settings.OutputLimit + 1); var readyState = sandboxer.StandardOutput.ReadLineAsync(); if (!readyState.Wait(settings.TimeLimit) || readyState.Result != "Ready") { if (!sandboxer.HasExited) { log.Error($"Песочница не завершилась через {settings.TimeLimit.TotalSeconds} секунд, убиваю её"); sandboxer.Kill(); result.Verdict = Verdict.SandboxError; result.Error = "Sandbox does not respond"; return; } if (sandboxer.ExitCode != 0) { HandleNonZeroExitCode(stderrReader.GetData(), sandboxer.ExitCode); return; } result.Verdict = Verdict.SandboxError; result.Error = "Sandbox exit before respond"; return; } sandboxer.Refresh(); var startUsedMemory = sandboxer.WorkingSet64; var startUsedTime = sandboxer.TotalProcessorTime; var startTime = DateTime.Now; sandboxer.StandardInput.WriteLine("Run"); sandboxer.StandardInput.WriteLineAsync(submission.Input); var stdoutReader = new AsyncReader(sandboxer.StandardOutput, settings.OutputLimit + 1); while (!sandboxer.HasExited && !IsTimeLimitExpected(sandboxer, startTime, startUsedTime) && !IsMemoryLimitExpected(sandboxer, startUsedMemory) && !IsOutputLimit(stdoutReader) && !IsOutputLimit(stderrReader)) { } if (!sandboxer.HasExited) sandboxer.Kill(); if (hasOutputLimit) { result.Verdict = Verdict.OutputLimit; return; } if (hasTimeLimit) { log.Error("Программа превысила ограничение по времени"); result.Verdict = Verdict.TimeLimit; return; } if (hasMemoryLimit) { log.Error("Программа превысила ограничение по памяти"); result.Verdict = Verdict.MemoryLimit; return; } sandboxer.WaitForExit(); if (sandboxer.ExitCode != 0) { HandleNonZeroExitCode(stderrReader.GetData(), sandboxer.ExitCode); return; } result.Output = stdoutReader.GetData(); result.Error = stderrReader.GetData(); }