Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 3 additions & 20 deletions DevProxy/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -406,28 +406,11 @@ static async Task<int> RunProxyAsync(string[] args, DevProxyConfigOptions option
{
// Reset the restart flag before each run
ConfigFileWatcher.Reset();
// RunProxyAsync only returns after the host has fully stopped, which
// means the proxy engine's shutdown (including system proxy
// deregistration) has completed — so it's safe to start a new instance.
exitCode = await RunProxyAsync(args, options);

// Wait for proxy to fully stop (including system proxy deregistration)
// before starting the new instance
if (ConfigFileWatcher.ProxyStoppedCompletionSource is not null)
{
var proxyStoppedTask = ConfigFileWatcher.ProxyStoppedCompletionSource.Task;
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(30));
#pragma warning disable VSTHRD003 // Intentionally waiting for external signal
var completedTask = await Task.WhenAny(proxyStoppedTask, timeoutTask);
#pragma warning restore VSTHRD003

// If the timeout elapses before the proxy signals it has stopped,
// continue to avoid hanging the restart loop indefinitely
if (completedTask == proxyStoppedTask)
{
#pragma warning disable VSTHRD003 // Observe exceptions from completed task
await proxyStoppedTask;
#pragma warning restore VSTHRD003
}
}

shouldRestart = ConfigFileWatcher.IsRestarting;
}
catch (Exception ex)
Expand Down
18 changes: 1 addition & 17 deletions DevProxy/Proxy/ConfigFileWatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,10 @@ sealed class ConfigFileWatcher(
/// </summary>
public static bool IsRestarting { get; private set; }

/// <summary>
/// Signaled when the proxy has fully stopped and system proxy is deregistered.
/// </summary>
public static TaskCompletionSource? ProxyStoppedCompletionSource { get; private set; }

/// <summary>
/// Resets the restart flag. Called before each proxy run.
/// </summary>
public static void Reset()
{
IsRestarting = false;
ProxyStoppedCompletionSource = null;
}

/// <summary>
/// Signals that the proxy has fully stopped.
/// </summary>
public static void SignalProxyStopped() => ProxyStoppedCompletionSource?.TrySetResult();
public static void Reset() => IsRestarting = false;

public Task StartAsync(CancellationToken cancellationToken)
{
Expand Down Expand Up @@ -93,14 +79,12 @@ private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
{
_logger.LogInformation("Configuration file changed. Restarting proxy...");
IsRestarting = true;
ProxyStoppedCompletionSource = new TaskCompletionSource();
_hostApplicationLifetime.StopApplication();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while handling configuration file change. Restart has not been initiated.");
IsRestarting = false;
ProxyStoppedCompletionSource = null;
}
}

Expand Down
Loading