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:
lincube
2026-05-07 21:39:21 +08:00
parent 84caca02bf
commit d8f75e86be
159 changed files with 8809 additions and 31 deletions

View File

@@ -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>