/// <inheritdoc /> public override async Task KillAsync() { // In the case that the process gets shut down by either its timeout or e.g. SandboxedProcessPipExecutor // detecting resource usage issues and calling KillAsync(), we flag the process with m_processKilled so we // don't process any more kernel reports that get pushed into report structure asynchronously! long incrementedValue = Interlocked.Increment(ref m_processKilledFlag); // Make sure this is done no more than once. if (incrementedValue == 1) { // surviving child processes may only be set when the process is explicitly killed m_survivingChildProcesses = NullIfEmpty(CoalesceProcesses(GetCurrentlyActiveChildProcesses())); await base.KillAsync(); KillAllChildProcesses(); SandboxConnection.NotifyRootProcessExited(PipId, this); await m_pendingReports.Completion; } }
/// <summary> /// Waits for all child processes to finish within a timeout limit and then termiantes all still running children after that point. /// After all the children have been taken care of, the method waits for pending report processing to finish, then returns the /// collected reports. /// </summary> internal override async Task <SandboxedProcessReports> GetReportsAsync() { SandboxConnection.NotifyRootProcessExited(PipId, this); if (!Killed) { var awaitedTask = await Task.WhenAny(m_pendingReports.Completion, m_processTreeTimeoutTask); if (awaitedTask == m_processTreeTimeoutTask) { LogProcessState("Waiting for reports timed out; any surviving processes will be forcefully killed."); await KillAsync(); } } // in any case must wait for pending reports to complete, because we must not freeze m_reports before that happens await m_pendingReports.Completion; // at this point this pip is done executing (it's only left to construct SandboxedProcessResult, // which is done by the base class) so notify the sandbox connection about it. SandboxConnection.NotifyPipFinished(PipId, this); return(IgnoreReportedAccesses ? null : m_reports); }