Ejemplo n.º 1
0
        /// <inheritdoc />
        public virtual async Task <SandboxedProcessResult> GetResultAsync()
        {
            Contract.Requires(Started);

            // 1: wait until process exits or process timeout is reached
            LogProcessState("Waiting for process to exit");
            var finishedTask = await Task.WhenAny(Task.Delay(ProcessInfo.Timeout.Value), WhenExited);

            m_exitTime = DateTime.UtcNow;

            // 2: kill process if timed out
            var timedOut = finishedTask != WhenExited;

            if (timedOut)
            {
                LogProcessState($"Process timed out after {ProcessInfo.Timeout.Value}; it will be forcefully killed.");
                await KillAsync();
            }

            // 3: wait for reports to be all received
            LogProcessState("Waiting for reports to be received");
            var reports = await GetReportsAsync();

            m_reportsReceivedTime = DateTime.UtcNow;
            reports?.Freeze();

            // 4: wait for stdout and stderr to be flushed
            LogProcessState("Waiting for stdout and stderr to be flushed");
            await Task.WhenAll(m_stdoutFlushedTcs.Task, m_stderrFlushedTcs.Task);

            var reportFileAccesses = ProcessInfo.FileAccessManifest?.ReportFileAccesses == true;
            var fileAccesses       = reportFileAccesses ? (reports?.FileAccesses ?? s_emptyFileAccessesSet) : null;

            return(new SandboxedProcessResult
            {
                ExitCode = timedOut ? ExitCodes.Timeout : Process.ExitCode,
                Killed = Killed,
                TimedOut = timedOut,
                HasDetoursInjectionFailures = HasSandboxFailures,
                StandardOutput = m_output.Freeze(),
                StandardError = m_error.Freeze(),
                HasReadWriteToReadFileAccessRequest = reports?.HasReadWriteToReadFileAccessRequest ?? false,
                AllUnexpectedFileAccesses = reports?.FileUnexpectedAccesses ?? s_emptyFileAccessesSet,
                FileAccesses = fileAccesses,
                DetouringStatuses = reports?.ProcessDetoursStatuses,
                ExplicitlyReportedFileAccesses = reports?.ExplicitlyReportedFileAccesses,
                Processes = CoalesceProcesses(reports?.Processes),
                MessageProcessingFailure = reports?.MessageProcessingFailure,
                DumpCreationException = m_dumpCreationException,
                DumpFileDirectory = ProcessInfo.TimeoutDumpDirectory,
                PrimaryProcessTimes = GetProcessTimes(),
                SurvivingChildProcesses = CoalesceProcesses(GetSurvivingChildProcesses())
            });
        }
Ejemplo n.º 2
0
        /// <inheritdoc />
        public async Task <SandboxedProcessResult> GetResultAsync()
        {
            Contract.Requires(Started);

            SandboxedProcessReports reports = null;

            await m_processExecutor.WaitForExitAsync();

            if (m_processExecutor.Killed)
            {
                // call here this.KillAsync() because a subclass may override it
                // to do some extra processing when a process is killed
                await KillAsync();
            }

            LogProcessState("Waiting for reports to be received");
            reports = await GetReportsAsync();

            m_reportsReceivedTime = DateTime.UtcNow;
            reports?.Freeze();

            await m_processExecutor.WaitForStdOutAndStdErrAsync();

            var reportFileAccesses = ProcessInfo.FileAccessManifest?.ReportFileAccesses == true;
            var fileAccesses       = reportFileAccesses ? (reports?.FileAccesses ?? s_emptyFileAccessesSet) : null;

            return(new SandboxedProcessResult
            {
                ExitCode = m_processExecutor.TimedOut ? ExitCodes.Timeout : Process.ExitCode,
                Killed = Killed,
                TimedOut = m_processExecutor.TimedOut,
                HasDetoursInjectionFailures = HasSandboxFailures,
                JobAccountingInformation = GetJobAccountingInfo(),
                StandardOutput = m_output.Freeze(),
                StandardError = m_error.Freeze(),
                HasReadWriteToReadFileAccessRequest = reports?.HasReadWriteToReadFileAccessRequest ?? false,
                AllUnexpectedFileAccesses = reports?.FileUnexpectedAccesses ?? s_emptyFileAccessesSet,
                FileAccesses = fileAccesses,
                DetouringStatuses = reports?.ProcessDetoursStatuses,
                ExplicitlyReportedFileAccesses = reports?.ExplicitlyReportedFileAccesses,
                Processes = CoalesceProcesses(reports?.Processes),
                MessageProcessingFailure = reports?.MessageProcessingFailure,
                DumpCreationException = m_dumpCreationException,
                DumpFileDirectory = ProcessInfo.TimeoutDumpDirectory,
                PrimaryProcessTimes = GetProcessTimes(),
                SurvivingChildProcesses = CoalesceProcesses(GetSurvivingChildProcesses())
            });
        }
Ejemplo n.º 3
0
        /// <inheritdoc />
        public virtual async Task <SandboxedProcessResult> GetResultAsync()
        {
            Contract.Requires(Started);

            var finishedTask = await Task.WhenAny(Task.Delay(ProcessInfo.Timeout.Value), Completion);

            var timedOut = finishedTask != Completion;

            if (timedOut)
            {
                LogDebugProcessState("Process timed out");
                await KillAsync();
            }

            var reports = await GetReportsAsync();

            reports?.Freeze();

            var reportFileAccesses = ProcessInfo.FileAccessManifest?.ReportFileAccesses == true;
            var fileAccesses       = reportFileAccesses ? (reports?.FileAccesses ?? s_emptyFileAccessesSet) : null;

            return(new SandboxedProcessResult
            {
                ExitCode = timedOut ? ExitCodes.Timeout : Process.ExitCode,
                Killed = Killed,
                TimedOut = timedOut,
                HasDetoursInjectionFailures = HasSandboxFailures,
                StandardOutput = m_output.Freeze(),
                StandardError = m_error.Freeze(),
                HasReadWriteToReadFileAccessRequest = reports?.HasReadWriteToReadFileAccessRequest ?? false,
                AllUnexpectedFileAccesses = reports?.FileUnexpectedAccesses ?? s_emptyFileAccessesSet,
                FileAccesses = fileAccesses,
                DetouringStatuses = reports?.ProcessDetoursStatuses,
                ExplicitlyReportedFileAccesses = reports?.ExplicitlyReportedFileAccesses,
                Processes = CoalesceProcesses(reports?.Processes),
                MessageProcessingFailure = reports?.MessageProcessingFailure,
                DumpCreationException = m_dumpCreationException,
                DumpFileDirectory = ProcessInfo.TimeoutDumpDirectory,
                PrimaryProcessTimes = GetProcessTimes(),
                SurvivingChildProcesses = CoalesceProcesses(GetSurvivingChildProcesses())
            });
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        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);
        }