Пример #1
0
        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");
        }
Пример #2
0
        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 = "";
            }
        }
Пример #3
0
 private bool CheckIsOutputLimit(AsyncReader reader)
 {
     return(hasOutputLimit = hasOutputLimit || reader.ReadedLength > settings.OutputLimit);
 }
Пример #4
0
 private bool IsOutputLimit(AsyncReader reader)
 {
     return(_hasOutputLimit = _hasOutputLimit ||
                              (reader.ReadedLength > OutputLimit));
 }
Пример #5
0
        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();
        }
Пример #6
0
		private bool IsOutputLimit(AsyncReader reader)
		{
			return _hasOutputLimit = _hasOutputLimit
									 || (reader.ReadedLength > OutputLimit);
		}
Пример #7
0
		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();
		}
Пример #8
0
        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();
        }
Пример #9
0
		private bool IsOutputLimit(AsyncReader reader)
		{
			return hasOutputLimit = hasOutputLimit
									|| (reader.ReadedLength > settings.OutputLimit);
		}
Пример #10
0
		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();
		}