in src/WebJobs.Script.WebHost/WebJobsScriptHostService.cs [556:653]
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 _activeStartupOperations.Keys)
{
_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;
var activeOperation = BeginStartupOperation(cancellationToken);
try
{
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
{
NotifyHostStopping(previousHost);
startTask = UnsynchronizedStartHostAsync(activeOperation);
stopTask = Orphan(previousHost, cancellationToken);
}
await startTask;
}
finally
{
EndStartupOperation(activeOperation);
}
_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();
}
}
}