internal void HookAutoRestartEvent() { const int ProcessExitHooked = 1; const int ProcessExitHandled = 2; int processExitHandling = 0; EventHandler localHandler = null; localHandler = async(_, __) => { try { if (Interlocked.Exchange(ref processExitHandling, ProcessExitHandled) == ProcessExitHooked) { Process.Exited -= localHandler; if (!_disposing) { await _host.OnProcessExited(Process).ConfigureAwait(false); } } } catch (Exception e) when(FatalError.Report(e)) { throw ExceptionUtilities.Unreachable; } }; // hook the event only once per process: if (Interlocked.Exchange(ref processExitHandling, ProcessExitHooked) == 0) { Process.Exited += localHandler; } }
private async void ProcessExitedHandler(object _, EventArgs __) { try { using (await _disposeSemaphore.DisposableWaitAsync().ConfigureAwait(false)) { if (_processExitHandlerStatus == ProcessExitHandlerStatus.Hooked) { Process.Exited -= ProcessExitedHandler; _processExitHandlerStatus = ProcessExitHandlerStatus.Handled; // Should set _processExitHandlerStatus before calling OnProcessExited to avoid deadlocks. // Calling the host should be within the lock to prevent its disposing during the execution. await _host.OnProcessExited(Process).ConfigureAwait(false); } } } catch (Exception e) when(FatalError.Report(e)) { throw ExceptionUtilities.Unreachable; } }