Skip to content

Commit

Permalink
修复在注册过程中对方断开导致异常但缺乏具体是连接哪一端的信息
Browse files Browse the repository at this point in the history
System.IO.IOException: Pipe is broken.
   at System.IO.Pipes.PipeStream.WriteCore(ReadOnlySpan`1 buffer)
   at System.IO.Pipes.PipeStream.Write(Byte[] buffer, Int32 offset, Int32 count)
   at System.IO.Stream.<>c.<BeginWriteInternal>b__48_0(Object <p0>)
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at System.IO.Stream.EndWrite(IAsyncResult asyncResult)
   at System.IO.Pipes.PipeStream.EndWrite(IAsyncResult asyncResult)
   at System.IO.Stream.<>c.<BeginEndWriteAsync>b__58_1(Stream stream, IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
--- End of stack trace from previous location ---
   at dotnetCampus.Ipc.Internals.IpcMessageConverter.WriteAsync(Stream stream, Byte[] messageHeader, Ack ack, IpcBufferMessageContext context, ISharedArrayPool pool)
   at dotnetCampus.Ipc.Pipes.IpcClientService.<>c__DisplayClass27_0.<<WriteMessageAsync>g__WriteMessageAsyncInner|0>d.MoveNext()
--- End of stack trace from previous location ---
   at dotnetCampus.Ipc.Utils.Extensions.DoubleBufferTaskExtensions.<>c__DisplayClass1_0.<<AddTaskAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at dotnetCampus.Ipc.Utils.Extensions.DoubleBufferTaskExtensions.AddTaskAsync(DoubleBufferTask`1 doubleBufferTask, Func`1 task)
   at dotnetCampus.Ipc.Pipes.IpcClientService.WriteMessageAsync(IpcMessageTracker`1 tracker)
   at dotnetCampus.Ipc.Pipes.IpcClientService.RegisterToPeer()
   at dotnetCampus.Ipc.Pipes.IpcClientService.StartInternalAsync(Boolean isReConnect, Boolean shouldRegisterToPeer)
   at dotnetCampus.Ipc.Pipes.IpcClientService.Start(Boolean shouldRegisterToPeer)
   at dotnetCampus.Ipc.Pipes.IpcProvider.CreatePeerProxyAsync(String peerName)
   at dotnetCampus.Ipc.Pipes.IpcProvider.GetOrCreatePeerProxyAsync(String peerName)
   at dotnetCampus.Ipc.Pipes.IpcProvider.GetAndConnectToPeerAsync(String peerName)
  • Loading branch information
lindexi committed Jan 8, 2024
1 parent 4e31585 commit 0b9609c
Showing 1 changed file with 25 additions and 14 deletions.
39 changes: 25 additions & 14 deletions src/dotnetCampus.Ipc/Pipes/IpcClientService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
Expand Down Expand Up @@ -269,7 +270,7 @@ internal async Task WriteMessageAsync(IpcMessageTracker<IpcBufferMessageContext>
// 这里的 InvalidOperationException 对应 DoubleBufferTask.AddTask 里抛出的异常。
// 在逻辑上确实是使用错误,抛出 InvalidOperationException 是合适的;
// 但因为 IPC 的断开发生在任何时刻,根本无法提前规避,所以实际上这里指的是 IPC 远端异常。
throw new IpcRemoteException($"因为已无法连接对方,所以 IPC 消息发送失败。Tag={tracker.Tag}", ex);
throw new IpcRemoteException($"因为已无法连接对方,所以 IPC 消息发送失败。Tag={tracker.Tag} LocalClient:'{IpcContext.PipeName}';RemoteServer:'{PeerName}'", ex);
// @lindexi,这里违背了异常处理原则里的“不应捕获使用异常”的原则,所以 DoubleBufferTask 的设计需要修改,加一个 TryAddTaskAsync 以应对并发场景。
}

Expand Down Expand Up @@ -307,19 +308,29 @@ async Task WriteMessageAsyncInner()

IpcContext.LogSendMessage(tracker.Message, PeerName);

// 发送消息。
await IpcMessageConverter.WriteAsync
(
stream,
IpcConfiguration.MessageHeader,
ack,
tracker.Message,
IpcConfiguration.SharedArrayPool
).ConfigureAwait(false);
await stream.FlushAsync().ConfigureAwait(false);

// 追踪消息。
tracker.Debug("IPC finish writing.");
try
{
// 发送消息。
await IpcMessageConverter.WriteAsync
(
stream,
IpcConfiguration.MessageHeader,
ack,
tracker.Message,
IpcConfiguration.SharedArrayPool
).ConfigureAwait(false);
await stream.FlushAsync().ConfigureAwait(false);

// 追踪消息。
tracker.Debug("IPC finish writing.");
}
catch (IOException e)
{
// 比如 Pipe is broken. 等异常
tracker.Debug("IPC write fail.");
// 此时无法知道是对方断开了连接,还是其他异常,因此决定这里抛出的是 IpcException 异常
throw new IpcException($"IPC write fail. Tag={tracker.Tag} LocalClient:'{IpcContext.PipeName}';RemoteServer:'{PeerName}'", e);
}
}
}

Expand Down

0 comments on commit 0b9609c

Please sign in to comment.