Fix: SSH tunnel not restarted on unexpected exit
- Add TunnelExited event to SshTunnelService - Null _process/_lastSpec and dispose the process on unexpected exit, then fire TunnelExited - Subscribe to TunnelExited in App.xaml.cs with bounded retry backoff (1s/2s/5s/10s/30s) Agent-Logs-Url: https://github.com/openclaw/openclaw-windows-node/sessions/a69d5952-fc73-46fe-9d2b-e5596c75ea4c Co-authored-by: shanselman <2892+shanselman@users.noreply.github.com>
This commit is contained in:
parent
9dcd12767a
commit
60f1ebde9a
@ -270,6 +270,7 @@ public partial class App : Application
|
||||
ToastNotificationManagerCompat.OnActivated += OnToastActivated;
|
||||
|
||||
_sshTunnelService = new SshTunnelService(new AppLogger());
|
||||
_sshTunnelService.TunnelExited += OnSshTunnelExited;
|
||||
|
||||
// First-run check
|
||||
if (string.IsNullOrWhiteSpace(_settings.Token))
|
||||
@ -2262,6 +2263,35 @@ public partial class App : Application
|
||||
return true;
|
||||
}
|
||||
|
||||
private async void OnSshTunnelExited(object? sender, EventArgs e)
|
||||
{
|
||||
if (_isExiting || _settings?.UseSshTunnel != true) return;
|
||||
|
||||
// Attempt to restart the SSH tunnel with bounded exponential backoff.
|
||||
// The gateway client's built-in reconnect loop will pick up automatically
|
||||
// once the tunnel port is available again.
|
||||
int[] retryDelays = [1000, 2000, 5000, 10000, 30000];
|
||||
for (int i = 0; i < retryDelays.Length; i++)
|
||||
{
|
||||
await Task.Delay(retryDelays[i]);
|
||||
if (_isExiting || _settings?.UseSshTunnel != true) return;
|
||||
try
|
||||
{
|
||||
if (EnsureSshTunnelConfigured())
|
||||
{
|
||||
Logger.Info("SSH tunnel successfully restarted after unexpected exit");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Warn($"SSH tunnel restart attempt {i + 1} failed: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Error("SSH tunnel could not be restarted after all retry attempts");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Microsoft.UI.Dispatching.DispatcherQueue? AppDispatcherQueue =>
|
||||
|
||||
@ -21,6 +21,11 @@ public sealed class SshTunnelService : IDisposable
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the SSH tunnel process exits unexpectedly (i.e., not as a result of <see cref="Stop"/>).
|
||||
/// </summary>
|
||||
public event EventHandler? TunnelExited;
|
||||
|
||||
public bool IsRunning => _process is { HasExited: false };
|
||||
|
||||
public void EnsureStarted(SettingsManager settings)
|
||||
@ -130,6 +135,10 @@ public sealed class SshTunnelService : IDisposable
|
||||
else
|
||||
{
|
||||
_logger.Warn($"SSH tunnel exited unexpectedly (code {exitCode})");
|
||||
_process = null;
|
||||
_lastSpec = null;
|
||||
try { process.Dispose(); } catch (Exception disposeEx) { _logger.Warn($"SSH tunnel process dispose failed: {disposeEx.Message}"); }
|
||||
TunnelExited?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user