public async Task <bool> WaitForExitAsync(TimeSpan timeout, CancellationToken token = default) { var sw = Stopwatch.StartNew(); loop: if (token.IsCancellationRequested) { return(false); } if (m_process != null) { int pid = m_process.Id; if (!await m_process.WaitForExitAsync(timeout, token).ConfigureAwait(false)) { return(false); } if (m_options.RestartAfterCrash && pid != m_process.Id) { // Process has been restarted. The "OnExit()" method is called during // WaitForExit(). So technically, the process has exited, but has been // restarted while the user has been waiting for it. So from the user's // point if view it is still running. // Account for total wait time, if any, and continue waiting. m_options.Events.OnHostRestart(pid, m_process.Id); if (timeout != TimeSpan.Zero) { timeout = timeout.Add(-sw.Elapsed); if (timeout <= TimeSpan.Zero) { return(false); } } goto loop; } int exitCode = m_process.ExitCode; if (exitCode != 0) { if (!m_options.Events.OnHostExitWithError(pid, exitCode)) { throw new IsolationException(string.Format(CultureInfo.InvariantCulture, "Host process failed with code {0}", ProcessUtils.GetExitCodeDescription(exitCode))); } } } return(true); }