private void RunInVm() { // (1) Serialize sandboxed prosess info. SerializeSandboxedProcessInfoToFile(); // (2) Create and serialize run request. var runRequest = new RunRequest { AbsolutePath = m_tool.ExecutablePath, Arguments = m_tool.CreateArguments(GetSandboxedProcessInfoFile(), GetSandboxedProcessResultsFile()), WorkingDirectory = GetOutputDirectory() }; VmSerializer.SerializeToFile(RunRequestPath, runRequest); // (2) Create a process to execute VmCommandProxy. string arguments = $"{VmCommands.Run} /{VmCommands.Params.InputJsonFile}:\"{RunRequestPath}\" /{VmCommands.Params.OutputJsonFile}:\"{RunOutputPath}\""; var process = CreateVmCommandProxyProcess(arguments); LogExternalExecution($"call (wd: {process.StartInfo.WorkingDirectory}) {m_vmInitializer.VmCommandProxy} {arguments}"); m_processExecutor = new AsyncProcessExecutor( process, TimeSpan.FromMilliseconds(-1), // Timeout should only be applied to the process that the external tool executes. line => AppendLineIfNotNull(m_output, line), line => AppendLineIfNotNull(m_error, line), SandboxedProcessInfo.Provenance, message => LogExternalExecution(message)); m_processExecutor.Start(); }
private static int InitializeVm(string inputFile) { Console.WriteLine($"Read initialize VM request from '{inputFile}'"); InitializeVmRequest request = VmSerializer.DeserializeFromFile <InitializeVmRequest>(inputFile); if (string.IsNullOrEmpty(request.SubstDrive) != string.IsNullOrEmpty(request.SubstPath)) { Console.Error.WriteLine("Invalid subst input"); return(1); } if (!string.IsNullOrEmpty(request.SubstDrive)) { if (request.SubstDrive.Length != 2 || !char.IsLetter(request.SubstDrive[0]) || request.SubstDrive[1] != ':') { Console.Error.WriteLine($"Invalid subst drive '{request.SubstDrive}'"); return(1); } } if (!string.IsNullOrEmpty(request.SubstPath)) { if (!Path.IsPathRooted(request.SubstPath) || request.SubstPath.EndsWith(Path.DirectorySeparatorChar.ToString())) { Console.Error.Write($"Invalid subst path '{request.SubstPath}'"); return(1); } } return(0); }
public override bool TryResumeProcess() => false; // Currently, only SandboxedProcess is supported. /// <inheritdoc /> public override async Task <SandboxedProcessResult> GetResultAsync() { Contract.Requires(m_processExecutor != null); // See the remarks of this class that BuildXL wants to execute a process P with SandboxedProcessInfo I // in the VM. // (1) Wait for VmCommandProxy to exit. await m_processExecutor.WaitForExitAsync(); await m_processExecutor.WaitForStdOutAndStdErrAsync(); // (2) Validate result of VmCommandProxy. if (m_processExecutor.TimedOut || m_processExecutor.Killed) { // If timed out/killed, then sandboxed process result may have not been deserialized yet. return(CreateResultForVmCommandProxyFailure()); } // Process.ExitCode is the exit code of VmCommandProxy, and not the exit code of SandboxedProcessExecutor // nor the exit code of the process P. if (Process.ExitCode != 0) { return(CreateResultForVmCommandProxyFailure()); } if (!FileUtilities.FileExistsNoFollow(RunOutputPath)) { m_error.AppendLine($"Could not find VM output file '{RunOutputPath}"); return(CreateResultForVmCommandProxyFailure()); } try { // (3) Validate the result of SandboxedProcessExecutor(P, I) that VmCommandProxy instructs the VM to execute. RunResult runVmResult = ExceptionUtilities.HandleRecoverableIOException( () => VmSerializer.DeserializeFromFile <RunResult>(RunOutputPath), e => m_error.AppendLine(e.Message)); if (runVmResult == null) { return(CreateResultForVmCommandProxyFailure()); } // runVmResult.ProcessStateInfo.ExitCode is the exit code of SandboxedProcessExecutor, and not // the exit code of the process P that SandboxedProcessExecutor executes. if (runVmResult.ProcessStateInfo.ExitCode != 0) { return(CreateResultForSandboxExecutorFailure(runVmResult)); } } catch (Exception e) { m_error.AppendLine(e.ToString()); return(CreateResultForVmCommandProxyFailure()); } return(DeserializeSandboxedProcessResultFromFile()); }
private static int StartBuild(string inputFile) { Console.WriteLine($"Read request from '{inputFile}'"); StartBuildRequest request = VmSerializer.DeserializeFromFile <StartBuildRequest>(inputFile); Console.WriteLine($"Start build request: "); Console.WriteLine($" - HostLowPrivilegeUsername: {request.HostLowPrivilegeUsername ?? string.Empty}"); Console.WriteLine($" - HostLowPrivilegePassword: {request.HostLowPrivilegePassword ?? string.Empty}"); return(0); }
public override async Task <SandboxedProcessResult> GetResultAsync() { Contract.Requires(m_processExecutor != null); // (1) Wait for VmCommandProxy. await m_processExecutor.WaitForExitAsync(); await m_processExecutor.WaitForStdOutAndStdErrAsync(); // (2) Validate result of VmCommandProxy. if (m_processExecutor.TimedOut || m_processExecutor.Killed) { // If timed out/killed, then sandboxed process result may have not been deserialized yet. return(CreateResultForVmCommandProxyFailure()); } if (Process.ExitCode != 0) { return(CreateResultForVmCommandProxyFailure()); } if (!FileUtilities.FileExistsNoFollow(RunOutputPath)) { m_error.AppendLine($"Could not find VM output file '{RunOutputPath}"); return(CreateResultForVmCommandProxyFailure()); } try { // (3) Validate the result of sandboxed process executor run by VmCommandProxy. RunResult runVmResult = ExceptionUtilities.HandleRecoverableIOException( () => VmSerializer.DeserializeFromFile <RunResult>(RunOutputPath), e => m_error.AppendLine(e.Message)); if (runVmResult == null) { return(CreateResultForVmCommandProxyFailure()); } if (runVmResult.ProcessStateInfo.ExitCode != 0) { return(CreateResultForSandboxExecutorFailure(runVmResult)); } } catch (Exception e) { m_error.AppendLine(e.ToString()); return(CreateResultForVmCommandProxyFailure()); } return(DeserializeSandboxedProcessResultFromFile()); }
private static int Run(string inputFile, string outputFile) { Console.WriteLine($"Read request from '{inputFile}'"); RunRequest request = VmSerializer.DeserializeFromFile <RunRequest>(inputFile); Console.WriteLine($"Run request '{request.AbsolutePath} {request.Arguments}'"); var stdOut = new StringBuilder(); var stdErr = new StringBuilder(); using (var process = new Process { StartInfo = new ProcessStartInfo { FileName = request.AbsolutePath, Arguments = request.Arguments, WorkingDirectory = request.WorkingDirectory, RedirectStandardError = true, RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true }, EnableRaisingEvents = true }) { process.OutputDataReceived += (s, e) => stdOut.AppendLine(e.Data); process.ErrorDataReceived += (s, e) => stdErr.AppendLine(e.Data); process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); Console.WriteLine($"Finish request '{request.AbsolutePath} {request.Arguments}'"); var stdOutPath = Path.Combine(request.WorkingDirectory, "vm.std.out"); var stdErrPath = Path.Combine(request.WorkingDirectory, "vm.std.err"); File.WriteAllText(stdOutPath, stdOut.ToString()); File.WriteAllText(stdErrPath, stdErr.ToString()); var result = new RunResult { StdOut = stdOut.ToString(), StdErr = stdErr.ToString(), ProcessStateInfo = new ProcessStateInfo { StdOutPath = stdOutPath, StdErrPath = stdErrPath, ExitCode = process.ExitCode, ProcessState = process.HasExited ? ProcessState.Exited : ProcessState.Unknown, TerminationReason = ProcessTerminationReason.None } }; Console.WriteLine($"Write result to '{outputFile}'"); VmSerializer.SerializeToFile(outputFile, result); return(0); } }