/// <summary> /// Deserializes sandboxed process result from file. /// </summary> protected SandboxedProcessResult DeserializeSandboxedProcessResultFromFile() { string file = SandboxedProcessResultsFile; Func <BuildXLReader, AbsolutePath> readPath = reader => { bool isAbsolutePath = reader.ReadBoolean(); if (isAbsolutePath) { return(reader.ReadAbsolutePath()); } else { string path = reader.ReadString(); return(AbsolutePath.Create(SandboxedProcessInfo.PathTable, path)); } }; try { using (FileStream stream = File.OpenRead(file)) { return(SandboxedProcessResult.Deserialize(stream, readPath)); } } catch (IOException ioException) { ThrowBuildXLException($"Failed to deserialize sandboxed process result '{file}'", ioException); return(null); } }
/// <inheritdoc /> public async Task <SandboxedProcessResult> GetResultAsync() { SandboxedProcessResult result = await m_resultTaskCompletionSource.Task; // await yield to make sure we are not blocking the thread that called us await Task.Yield(); return(result); }
/// <summary> /// Deserializes sandboxed process result from file. /// </summary> /// <returns></returns> protected SandboxedProcessResult DeserializeSandboxedProcessResultFromFile() { string file = GetSandboxedProcessResultsFile(); try { using (FileStream stream = File.OpenRead(file)) { return(SandboxedProcessResult.Deserialize(stream)); } } catch (IOException ioException) { ThrowBuildXLException($"Failed to deserialize sandboxed process result '{file}'", ioException); return(null); } }
private void SetResult(SandboxedProcessResult result) { Contract.Requires(m_detouredProcess != null); m_resultTaskCompletionSource.SetResult(result); }
private async Task OnProcessExited() { // Wait until all incoming report messages from the detoured process have been handled. await WaitUntilReportEof(m_detouredProcess.Killed); // Ensure no further modifications to the report m_reports?.Freeze(); // We can get extended accounting information (peak memory, etc. rolled up for the entire process tree) if this process was wrapped in a job. JobObject.AccountingInformation?jobAccountingInformation = null; JobObject jobObject = m_detouredProcess.GetJobObject(); if (jobObject != null) { jobAccountingInformation = jobObject.GetAccountingInformation(); } ProcessTimes primaryProcessTimes = m_detouredProcess.GetTimesForPrimaryProcess(); IOException standardInputException = null; try { await m_standardInputTcs.Task; } catch (IOException ex) { standardInputException = ex; } // Construct result; note that the process is expected to have exited at this point, even if we decided to forcefully kill it // (this callback is always a result of the process handle being signaled). int exitCode = 0; if (m_reports?.MessageProcessingFailure != null) { exitCode = ExitCodes.MessageProcessingFailure; } else { Contract.Assert(m_detouredProcess.HasExited, "Detoured process has not been marked as exited"); exitCode = m_detouredProcess.GetExitCode(); } SandboxedProcessResult result = new SandboxedProcessResult { // If there is a message parsing failure, fail the pip. ExitCode = exitCode, Killed = m_detouredProcess.Killed, TimedOut = m_detouredProcess.TimedOut, HasDetoursInjectionFailures = m_detouredProcess.HasDetoursInjectionFailures, SurvivingChildProcesses = m_survivingChildProcesses?.Values.ToArray(), PrimaryProcessTimes = primaryProcessTimes, JobAccountingInformation = jobAccountingInformation, StandardOutput = m_output.Freeze(), StandardError = m_error.Freeze(), AllUnexpectedFileAccesses = m_reports?.FileUnexpectedAccesses, FileAccesses = m_reports?.FileAccesses, DetouringStatuses = m_reports?.ProcessDetoursStatuses, ExplicitlyReportedFileAccesses = m_reports?.ExplicitlyReportedFileAccesses, Processes = m_reports?.Processes, DumpFileDirectory = m_detouredProcess.DumpFileDirectory, DumpCreationException = m_detouredProcess.DumpCreationException, StandardInputException = standardInputException, MessageProcessingFailure = m_reports?.MessageProcessingFailure, ProcessStartTime = m_detouredProcess.StartTime, HasReadWriteToReadFileAccessRequest = m_reports?.HasReadWriteToReadFileAccessRequest ?? false, }; SetResult(result); }
private async Task OnProcessExitedAsync() { // Wait until all incoming report messages from the detoured process have been handled. await WaitUntilReportEof(m_detouredProcess.Killed); // Ensure no further modifications to the report m_reports?.Freeze(); // We can get extended accounting information (peak memory, etc. rolled up for the entire process tree) if this process was wrapped in a job. JobObject.AccountingInformation?jobAccountingInformation = null; JobObject jobObject = m_detouredProcess.GetJobObject(); if (jobObject != null) { var accountingInfo = jobObject.GetAccountingInformation(); // Only overwrite memory counters if <see cref="GetMemoryCountersSnapshot"/> did get triggered previously. This isn't the case if the // detours sandbox is used outside of BuildXL (currently only the scheduler calls this). The <see cref="JobObject.GetAccountingInformation"/> // function does populate memory counters for the process tree if possible, so don't overwrite them with empty aggregator values. if (m_peakWorkingSet.Count > 0 || m_workingSet.Count > 0 || m_peakCommitSize.Count > 0 || m_commitSize.Count > 0) { accountingInfo.MemoryCounters = Pips.ProcessMemoryCounters.CreateFromBytes( peakWorkingSet: Convert.ToUInt64(m_peakWorkingSet.Maximum), averageWorkingSet: Convert.ToUInt64(m_workingSet.Average), peakCommitSize: Convert.ToUInt64(m_peakCommitSize.Maximum), averageCommitSize: Convert.ToUInt64(m_commitSize.Average)); } jobAccountingInformation = accountingInfo; } ProcessTimes primaryProcessTimes = m_detouredProcess.GetTimesForPrimaryProcess(); IOException standardInputException = null; try { await m_standardInputTcs.Task; } catch (IOException ex) { standardInputException = ex; } // Construct result; note that the process is expected to have exited at this point, even if we decided to forcefully kill it // (this callback is always a result of the process handle being signaled). int exitCode = 0; if (m_reports?.MessageProcessingFailure != null) { exitCode = ExitCodes.MessageProcessingFailure; } else { Contract.Assert(m_detouredProcess.HasExited, "Detoured process has not been marked as exited"); exitCode = m_detouredProcess.GetExitCode(); } SandboxedProcessResult result = new SandboxedProcessResult { // If there is a message parsing failure, fail the pip. ExitCode = exitCode, Killed = m_detouredProcess.Killed, TimedOut = m_detouredProcess.TimedOut, HasDetoursInjectionFailures = m_detouredProcess.HasDetoursInjectionFailures, SurvivingChildProcesses = m_survivingChildProcesses?.Values.ToArray(), PrimaryProcessTimes = primaryProcessTimes, JobAccountingInformation = jobAccountingInformation, StandardOutput = m_output.Freeze(), StandardError = m_error.Freeze(), AllUnexpectedFileAccesses = m_reports?.FileUnexpectedAccesses, FileAccesses = m_reports?.FileAccesses, DetouringStatuses = m_reports?.ProcessDetoursStatuses, ExplicitlyReportedFileAccesses = m_reports?.ExplicitlyReportedFileAccesses, Processes = m_reports?.Processes, DumpFileDirectory = m_detouredProcess.DumpFileDirectory, DumpCreationException = m_detouredProcess.DumpCreationException, StandardInputException = standardInputException, MessageProcessingFailure = m_reports?.MessageProcessingFailure, ProcessStartTime = m_detouredProcess.StartTime, HasReadWriteToReadFileAccessRequest = m_reports?.HasReadWriteToReadFileAccessRequest ?? false, DiagnosticMessage = m_detouredProcess.Diagnostics }; SetResult(result); }