/// <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);
            }
        }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
        /// <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);
            }
        }
Exemple #4
0
        private void SetResult(SandboxedProcessResult result)
        {
            Contract.Requires(m_detouredProcess != null);

            m_resultTaskCompletionSource.SetResult(result);
        }
Exemple #5
0
        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);
        }