コード例 #1
0
                public Task EnterFromAsync(LauncherBase p, State fromState)
                {
                    if (TryEnter(p, fromState))
                    {
                    }

                    return(Task.CompletedTask);
                }
コード例 #2
0
                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);
                }
コード例 #3
0
            /// <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);
            }
コード例 #4
0
                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));
                }
コード例 #5
0
        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));
        }
コード例 #6
0
 private static void LogProcessCount(LauncherBase p, int processCount)
 {
     try
     {
         p._logger?.LogInformation("Process Count: {ProcessCount}", processCount);
     }
     catch
     {
         // Prevent logging exception from causing havoc
     }
 }
コード例 #7
0
 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);
 }
コード例 #8
0
        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);
        }
コード例 #9
0
 /// <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
     }
 }
コード例 #10
0
                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();
                    }
                }
コード例 #11
0
        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();
        }
コード例 #12
0
        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);
        }
コード例 #13
0
 public Task EnterFromAsync(LauncherBase p, State fromState, TimeSpan timeout)
 => !TryEnter(p, fromState) ? p._currentState.ExitAsync(p, timeout) : ExitAsync(p, timeout);
コード例 #14
0
 public override Task StartAsync(LauncherBase p) => p._startCompletionSource.Task;
コード例 #15
0
 public override Task KillAsync(LauncherBase p) => StateManager.Killing.EnterFromAsync(p, this);
コード例 #16
0
 public override Task WaitForExitAsync(LauncherBase p) => Task.CompletedTask;
コード例 #17
0
 public override Task EnterFromAsync(LauncherBase p, State fromState, TimeSpan timeout)
 => !StateManager.TryEnter(p, fromState, this) ? StateManager.CurrentState.ExitAsync(p, timeout) : ExitAsync(p, timeout);
コード例 #18
0
 public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => Task.CompletedTask;
コード例 #19
0
 public override Task KillAsync(LauncherBase p) => Task.CompletedTask;
コード例 #20
0
 public override void Dispose(LauncherBase p)
 {
     // Nothing to do
 }
コード例 #21
0
 public override void Dispose(LauncherBase p)
 {
     p._startCompletionSource.TrySetException(new ObjectDisposedException(p.ToString()));
     base.Dispose(p);
 }
コード例 #22
0
 public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => throw new ObjectDisposedException(p.ToString());
コード例 #23
0
 public override Task KillAsync(LauncherBase p) => throw new ObjectDisposedException(p.ToString());
コード例 #24
0
                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;
                    }
                }
コード例 #25
0
 protected override void Leave(LauncherBase p)
 => LogProcessCount(p, Interlocked.Decrement(ref _processCount));
コード例 #26
0
 public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => WaitForExitAsync(p);
コード例 #27
0
 public override Task StartAsync(LauncherBase p) => Task.CompletedTask;
コード例 #28
0
 public override Task ExitAsync(LauncherBase p, TimeSpan timeout) => Exiting.EnterFromAsync(p, this, timeout);
コード例 #29
0
 public override Task KillAsync(LauncherBase p) => WaitForExitAsync(p);
コード例 #30
0
 public override Task KillAsync(LauncherBase p) => Killing.EnterFromAsync(p, this);