private void WaitForExit(AppDomain sandbox, SandboxHook hook, string executableFilePath, string[] arguments, ref string stdout, ref string stderr, ref int exitCode, ref bool hasExited) { try { exitCode = sandbox.ExecuteAssembly(executableFilePath, arguments); } catch (Exception ex) { stderr += ex.Message; } finally { var tempStderr = ""; hook.GetOutput(out stdout, out tempStderr); stderr += tempStderr; hasExited = true; } }
public override bool Execute(CheckParameters parameters, ref string output, ref string errors, ref double usedTime, ref double usedMemory, bool isChecker) { var extension = Path.GetExtension(parameters.FileName); var executableFilePath = parameters.FileName.Substring(0, parameters.FileName.Length - extension.Length) + ".exe"; var inputFilePath = isChecker ? ((CheckParametersForChecker)parameters).SolutionOutputFileName : parameters.InputTestFileName; var timeLimit = parameters.TimeLimit; if (timeLimit == 0) { timeLimit = 120; //2 mins } if (!File.Exists(executableFilePath)) { //errors += "If you see this message, please contact administrator (ExErr1)."; errors += "Если Вы видите это сообщение, пожалуйста, свяжитесь с администратором (ExErr1)."; return(false); } if (!File.Exists(inputFilePath)) { //errors += "If you see this message, please contact administrator (ExErr2)."; errors += "Если Вы видите это сообщение, пожалуйста, свяжитесь с администратором (ExErr2)."; return(false); } if (isChecker) { if (!File.Exists(parameters.InputTestFileName)) { //errors += "If you see this message, please contact administrator (ExErr3)."; errors += "Если Вы видите это сообщение, пожалуйста, свяжитесь с администратором (ExErr3)."; return(false); } if (!File.Exists(parameters.OutputTestFileName)) { //errors += "If you see this message, please contact administrator (ExErr4)."; errors += "Если Вы видите это сообщение, пожалуйста, свяжитесь с администратором (ExErr4)."; return(false); } } bool hasExited = false; bool hasLimitExceptions = false; int exitCode = 0; string stdout = "", stderr = ""; string limitStderr = ""; double tempUsedTime = 0; double tempUsedMemory = 0; var assemblyFileName = Path.GetDirectoryName(inputFilePath).Replace("App_Data", @"bin\CPTLib.dll"); try { PermissionSet ps = new PermissionSet(PermissionState.None); ps.AddPermission(new UIPermission(PermissionState.Unrestricted)); ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)); ps.AddPermission(new FileIOPermission( FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, assemblyFileName)); ps.AddPermission(new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, executableFilePath)); ps.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, inputFilePath)); if (isChecker) { ps.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, parameters.InputTestFileName)); ps.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, parameters.OutputTestFileName)); } AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation; setup.ShadowCopyFiles = "true"; var sandbox = AppDomain.CreateDomain("Sandbox", null, setup, ps); AppDomain.MonitoringIsEnabled = true; TextReader inputFileReader = new StreamReader(inputFilePath); string[] arguments = isChecker ? new string[] { inputFilePath, parameters.InputTestFileName, parameters.OutputTestFileName } : new string[] { inputFilePath }; try { var hookName = typeof(SandboxHook).FullName; ObjectHandle obj = sandbox.CreateInstanceFrom(assemblyFileName, hookName); using (SandboxHook hook = (SandboxHook)obj.Unwrap()) { hook.Capture(inputFileReader == null ? String.Empty : inputFileReader.ReadToEnd()); inputFileReader.Close(); var t = new Task( () => WaitForExit(sandbox, hook, executableFilePath, arguments, ref stdout, ref stderr, ref exitCode, ref hasExited)); t.Start(); var t2 = new Task( () => CheckTimeLimit(sandbox, timeLimit, parameters.MemoryLimit, ref tempUsedTime, ref tempUsedMemory, ref limitStderr, ref hasExited, ref hasLimitExceptions)); t2.Start(); Task.WaitAll(t, t2); } } finally { if (!hasLimitExceptions) { AppDomain.Unload(sandbox); } } } catch (Exception ex) { errors += hasLimitExceptions ? "" : ex.Message + "\r\n"; } output += stdout; errors += hasLimitExceptions ? limitStderr : stderr; usedTime = tempUsedTime; usedMemory = tempUsedMemory; if (File.Exists(executableFilePath)) { try { File.Delete(executableFilePath); } catch (Exception) { } } return(hasExited && errors == "" && exitCode == 0); }