/// <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() { if (!Killed) { var waitTimeMs = ProcessInfo.NestedProcessTerminationTimeout.TotalMilliseconds * m_processInfo.SandboxedKextConnection.NumberOfKextConnections; var waitTime = TimeSpan.FromMilliseconds(waitTimeMs); var childProcessTimeoutTask = Task.Delay(ProcessInfo.NestedProcessTerminationTimeout); var awaitedTask = await Task.WhenAny(childProcessTimeoutTask, m_pendingReports.Completion); if (awaitedTask == childProcessTimeoutTask) { m_survivingChildProcesses = CoalesceProcesses(m_reports.GetCurrentlyActiveProcesses()); 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 kernel extension connection manager about it. m_processInfo.SandboxedKextConnection.NotifyKextProcessFinished(PipId, this); return(m_reports); }
/// <summary> /// This method reads some collections from the non-thread-safe <see cref="m_reports"/> object. /// The callers must make sure that when they call this method no concurrent modifications are /// being done to <see cref="m_reports"/>. /// </summary> private IReadOnlyList <ReportedProcess> GetCurrentlyActiveProcesses() { return(m_reports.GetCurrentlyActiveProcesses()); }