示例#1
0
        private async Task StartHostAsync(CancellationToken cancellationToken, int attemptCount = 0,
                                          JobHostStartupMode startupMode = JobHostStartupMode.Normal, Guid?parentOperationId = null)
        {
            // Add this to the list of trackable startup operations. Restarts can use this to cancel any ongoing or pending operations.
            var activeOperation = ScriptHostStartupOperation.Create(cancellationToken, _logger, parentOperationId);

            using (_metricsLogger.LatencyEvent(MetricEventNames.ScriptHostManagerStartService))
            {
                try
                {
                    await _hostStartSemaphore.WaitAsync();

                    // Now that we're inside the semaphore, set this task as completed. This prevents
                    // restarts from being invoked (via the PlaceholderSpecializationMiddleware) before
                    // the IHostedService has ever started.
                    _hostStartedSource.TrySetResult(true);

                    await UnsynchronizedStartHostAsync(activeOperation, attemptCount, startupMode);
                }
                finally
                {
                    activeOperation.Dispose();
                    _hostStartSemaphore.Release();
                }
            }
        }
示例#2
0
        public async Task RestartHostAsync(CancellationToken cancellationToken)
        {
            if (ShutdownRequested)
            {
                return;
            }

            using (_metricsLogger.LatencyEvent(MetricEventNames.ScriptHostManagerRestartService))
            {
                // Do not invoke a restart if the host has not yet been started. This can lead
                // to invalid state.
                if (!_hostStarted.IsCompleted)
                {
                    _logger.RestartBeforeStart();
                    await _hostStarted;
                }

                _logger.EnteringRestart();

                // If anything is mid-startup, cancel it.
                _startupLoopTokenSource?.Cancel();
                foreach (var startupOperation in ScriptHostStartupOperation.ActiveOperations)
                {
                    _logger.CancelingStartupOperationForRestart(startupOperation.Id);
                    try
                    {
                        startupOperation.CancellationTokenSource.Cancel();
                    }
                    catch (ObjectDisposedException)
                    {
                        // This can be disposed at any time.
                    }
                }

                try
                {
                    await _hostStartSemaphore.WaitAsync();

                    if (State == ScriptHostState.Stopping || State == ScriptHostState.Stopped)
                    {
                        _logger.SkipRestart(State.ToString());
                        return;
                    }

                    State = ScriptHostState.Default;
                    _logger.Restarting();

                    var previousHost = ActiveHost;
                    ActiveHost = null;

                    using (var activeOperation = ScriptHostStartupOperation.Create(cancellationToken, _logger))
                    {
                        Task startTask, stopTask;

                        // If we are running in development mode with core tools, do not overlap the restarts.
                        // Overlapping restarts are problematic when language worker processes are listening
                        // to the same debug port
                        if (ShouldEnforceSequentialRestart())
                        {
                            stopTask = Orphan(previousHost, cancellationToken);
                            await stopTask;
                            startTask = UnsynchronizedStartHostAsync(activeOperation);
                        }
                        else
                        {
                            startTask = UnsynchronizedStartHostAsync(activeOperation);
                            stopTask  = Orphan(previousHost, cancellationToken);
                        }

                        await startTask;
                    }

                    _logger.Restarted();
                }
                catch (OperationCanceledException)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        _logger.ScriptHostServiceRestartCanceledByRuntime();
                        throw;
                    }

                    // If the exception was triggered by our startup operation cancellation token, just ignore as
                    // it doesn't indicate an issue.
                }
                finally
                {
                    _hostStartSemaphore.Release();
                }
            }
        }