public Task EnterFromAsync(LauncherBase p, State fromState) { if (TryEnter(p, fromState)) { } return(Task.CompletedTask); }
public Task EnterFromAsync(LauncherBase p, State fromState) { if (TryEnter(p, fromState)) { // Process has not exited or been killed since transition to this state was initiated LogProcessCount(p, Interlocked.Increment(ref _processCount)); } return(Task.CompletedTask); }
/// <summary> /// Attempts thread-safe transitions from a given state to this state. /// </summary> /// <param name="p">The Base process</param> /// <param name="fromState">The state from which state transition takes place</param> /// <returns>Returns <c>true</c> if transition is successful, or <c>false</c> if transition /// cannot be made because current state does not equal <paramref name="fromState"/>.</returns> protected bool TryEnter(LauncherBase p, State fromState) { if (Interlocked.CompareExchange(ref p._currentState, this, fromState) == fromState) { fromState.Leave(p); return(true); } return(false); }
public Task EnterFromAsync(LauncherBase p, State fromState) { if (!TryEnter(p, fromState)) { // Delegate StartAsync to current state, because it has already changed since // transition to this state was initiated. return(p._currentState.StartAsync(p)); } return(StartCoreAsync(p)); }
public override Task EnterFromAsync(LauncherBase p, State fromState, TimeSpan timeout) { if (!StateManager.TryEnter(p, fromState, this)) { // Delegate StartAsync to current state, because it has already changed since // transition to this state was initiated. return(StateManager.CurrentState.StartAsync(p)); } return(StartCoreAsync(p)); }
private static void LogProcessCount(LauncherBase p, int processCount) { try { p._logger?.LogInformation("Process Count: {ProcessCount}", processCount); } catch { // Prevent logging exception from causing havoc } }
public override async Task ExitAsync(LauncherBase p, TimeSpan timeout) { var waitForExitTask = WaitForExitAsync(p); await waitForExitTask.WithTimeout( async() => { await StateManager.Killing.EnterFromAsync(p, this, timeout).ConfigureAwait(false); await waitForExitTask.ConfigureAwait(false); }, timeout, CancellationToken.None).ConfigureAwait(false); }
public override Task EnterFromAsync(LauncherBase p, State fromState, TimeSpan timeSpan) { if (fromState == StateManager.Exited) { return(null); } Kill(p); p.ExitCompletionSource.TrySetException(new ObjectDisposedException(p.ToString())); p.TempUserDataDir?.Dispose(); return(null); }
/// <summary> /// Kills process if it is still alive. /// </summary> /// <param name="p"></param> private static void Kill(LauncherBase p) { try { if (!p.Process.HasExited) { p.Process.Kill(); } } catch (InvalidOperationException) { // Ignore } }
public void EnterFrom(LauncherBase p, State fromState) { if (!TryEnter(p, fromState)) { // Delegate Dispose to current state, because it has already changed since // transition to this state was initiated. p._currentState.Dispose(p); } else if (fromState != Exited) { Kill(p); p._exitCompletionSource.TrySetException(new ObjectDisposedException(p.ToString())); p.TempUserDataDir?.Dispose(); } }
public void EnterFrom(LauncherBase p, State fromState) { while (!StateManager.TryEnter(p, fromState, this)) { // Current state has changed since transition to this state was requested. // Therefore retry transition to this state from the current state. This ensures // that Leave() operation of current state is properly called. fromState = StateManager.CurrentState; if (fromState == this) { return; } } p.ExitCompletionSource.TrySetResult(true); p.TempUserDataDir?.Dispose(); }
public override async Task EnterFromAsync(LauncherBase p, State fromState, TimeSpan timeout) { if (!StateManager.TryEnter(p, fromState, this)) { // Delegate KillAsync to current state, because it has already changed since // transition to this state was initiated. await StateManager.CurrentState.KillAsync(p).ConfigureAwait(false); } try { if (!p.Process.HasExited) { p.Process.Kill(); } } catch (InvalidOperationException) { // Ignore return; } await WaitForExitAsync(p).ConfigureAwait(false); }
public Task EnterFromAsync(LauncherBase p, State fromState, TimeSpan timeout) => !TryEnter(p, fromState) ? p._currentState.ExitAsync(p, timeout) : ExitAsync(p, timeout);
public override Task StartAsync(LauncherBase p) => p._startCompletionSource.Task;
public override Task KillAsync(LauncherBase p) => StateManager.Killing.EnterFromAsync(p, this);
public override Task WaitForExitAsync(LauncherBase p) => Task.CompletedTask;
public override Task EnterFromAsync(LauncherBase p, State fromState, TimeSpan timeout) => !StateManager.TryEnter(p, fromState, this) ? StateManager.CurrentState.ExitAsync(p, timeout) : ExitAsync(p, timeout);
public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => Task.CompletedTask;
public override Task KillAsync(LauncherBase p) => Task.CompletedTask;
public override void Dispose(LauncherBase p) { // Nothing to do }
public override void Dispose(LauncherBase p) { p._startCompletionSource.TrySetException(new ObjectDisposedException(p.ToString())); base.Dispose(p); }
public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => throw new ObjectDisposedException(p.ToString());
public override Task KillAsync(LauncherBase p) => throw new ObjectDisposedException(p.ToString());
private async Task StartCoreAsync(LauncherBase p) { var output = new StringBuilder(); void OnProcessDataReceivedWhileStarting(object sender, DataReceivedEventArgs e) { if (e.Data != null) { output.AppendLine(e.Data); var match = Regex.Match(e.Data, "^DevTools listening on (ws:\\/\\/.*)"); if (match.Success) { p._startCompletionSource.TrySetResult(match.Groups[1].Value); } } } void OnProcessExitedWhileStarting(object sender, EventArgs e) => p._startCompletionSource.TrySetException(new ProcessException($"Failed to launch Base! {output}")); void OnProcessExited(object sender, EventArgs e) => Exited.EnterFrom(p, p._currentState); p.Process.ErrorDataReceived += OnProcessDataReceivedWhileStarting; p.Process.Exited += OnProcessExitedWhileStarting; p.Process.Exited += OnProcessExited; CancellationTokenSource cts = null; try { p.Process.Start(); await Started.EnterFromAsync(p, this).ConfigureAwait(false); p.Process.BeginErrorReadLine(); int timeout = p._options.Timeout; if (timeout > 0) { cts = new CancellationTokenSource(timeout); cts.Token.Register(() => p._startCompletionSource.TrySetException( new ProcessException($"Timed out after {timeout} ms while trying to connect to Base!"))); } try { await p._startCompletionSource.Task.ConfigureAwait(false); await Started.EnterFromAsync(p, this).ConfigureAwait(false); } catch { await Killing.EnterFromAsync(p, this).ConfigureAwait(false); throw; } } finally { cts?.Dispose(); p.Process.Exited -= OnProcessExitedWhileStarting; p.Process.ErrorDataReceived -= OnProcessDataReceivedWhileStarting; } }
protected override void Leave(LauncherBase p) => LogProcessCount(p, Interlocked.Decrement(ref _processCount));
public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => WaitForExitAsync(p);
public override Task StartAsync(LauncherBase p) => Task.CompletedTask;
public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => Exiting.EnterFromAsync(p, this, timeout);
public override Task KillAsync(LauncherBase p) => WaitForExitAsync(p);
public override Task KillAsync(LauncherBase p) => Killing.EnterFromAsync(p, this);