mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
Add IPC backoff/retries and safer disposal
Introduce exponential backoff, jitter and retry logic across IPC components to improve robustness and avoid tight retry loops; make disposal idempotent and add connection guards. Key changes: - LauncherCoordinatorIpcServer / LauncherIpcServer: add backoff constants, ComputeBackoff(), consecutive error tracking and delayed retries with jitter. - LanMountainDesktopIpcClient / LauncherIpcClient: add connect retry loops, timeouts, delayed retries, improved error logging, and use ArrayPool for buffered async writes; ensure proper cleanup on failures. - PublicIpcHostService: add disposed flag, guard OnPeerConnected and Dispose, and clear connected peers on dispose. - Add many auto-generated commit analysis docs under docs/auto_commit_md and new scripts for analyzing/generating commit docs. These changes aim to make IPC connection handling more resilient and resource-safe.
This commit is contained in:
@@ -19,10 +19,14 @@ public class LauncherIpcServer : IDisposable
|
||||
|
||||
/// <summary>
|
||||
/// 协议:每条消息以 4 字节小端 int32 长度前缀开头,后跟 UTF-8 JSON 正文。
|
||||
/// 这在 Windows Message 模式和 Unix Byte 模式下均能可靠工作。
|
||||
/// 这在 Windows Message 模式和 unix Byte 模式下均能可靠工作。
|
||||
/// </summary>
|
||||
private const int LengthPrefixSize = 4;
|
||||
|
||||
private const int BackoffBaseMs = 200;
|
||||
private const int BackoffMaxMs = 5000;
|
||||
private const int BackoffJitterMs = 100;
|
||||
|
||||
public LauncherIpcServer(Action<StartupProgressMessage> onProgress)
|
||||
{
|
||||
_onProgress = onProgress;
|
||||
@@ -38,6 +42,8 @@ public class LauncherIpcServer : IDisposable
|
||||
|
||||
private async Task ListenLoopAsync()
|
||||
{
|
||||
var consecutiveErrors = 0;
|
||||
|
||||
while (!_cts.Token.IsCancellationRequested)
|
||||
{
|
||||
NamedPipeServerStream? pipe = null;
|
||||
@@ -47,12 +53,14 @@ public class LauncherIpcServer : IDisposable
|
||||
LauncherIpcConstants.PipeName,
|
||||
PipeDirection.In,
|
||||
1,
|
||||
PipeTransmissionMode.Byte);
|
||||
PipeTransmissionMode.Byte,
|
||||
PipeOptions.Asynchronous);
|
||||
|
||||
_currentPipe = pipe;
|
||||
await pipe.WaitForConnectionAsync(_cts.Token);
|
||||
|
||||
// 持久连接:在同一连接上循环读取多条消息,直到客户端断开
|
||||
consecutiveErrors = 0;
|
||||
|
||||
await ReadMessagesFromConnectionAsync(pipe, _cts.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -61,7 +69,7 @@ public class LauncherIpcServer : IDisposable
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
// 客户端断开连接,继续等待新连接
|
||||
consecutiveErrors = 0;
|
||||
continue;
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
@@ -70,10 +78,12 @@ public class LauncherIpcServer : IDisposable
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine($"IPC listen error: {ex.Message}");
|
||||
consecutiveErrors++;
|
||||
var delay = ComputeBackoff(consecutiveErrors);
|
||||
Console.Error.WriteLine($"IPC listen error (attempt {consecutiveErrors}), retrying in {delay}ms: {ex.Message}");
|
||||
try
|
||||
{
|
||||
await Task.Delay(200, _cts.Token);
|
||||
await Task.Delay(delay, _cts.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -96,6 +106,14 @@ public class LauncherIpcServer : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
private int ComputeBackoff(int attempt)
|
||||
{
|
||||
var exponential = BackoffBaseMs * (1 << Math.Min(attempt - 1, 5));
|
||||
var capped = Math.Min(exponential, BackoffMaxMs);
|
||||
var jitter = Random.Shared.Next(0, BackoffJitterMs);
|
||||
return capped + jitter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从已连接的管道中持续读取消息,直到连接断开或取消
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user