From 0b9609cfdc381e88f1a02a6c9396d03df91c16cd Mon Sep 17 00:00:00 2001 From: lindexi Date: Mon, 8 Jan 2024 15:42:34 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9C=A8=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E8=BF=87=E7=A8=8B=E4=B8=AD=E5=AF=B9=E6=96=B9=E6=96=AD?= =?UTF-8?q?=E5=BC=80=E5=AF=BC=E8=87=B4=E5=BC=82=E5=B8=B8=E4=BD=86=E7=BC=BA?= =?UTF-8?q?=E4=B9=8F=E5=85=B7=E4=BD=93=E6=98=AF=E8=BF=9E=E6=8E=A5=E5=93=AA?= =?UTF-8?q?=E4=B8=80=E7=AB=AF=E7=9A=84=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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.b__48_0(Object ) 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.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.<g__WriteMessageAsyncInner|0>d.MoveNext() --- End of stack trace from previous location --- at dotnetCampus.Ipc.Utils.Extensions.DoubleBufferTaskExtensions.<>c__DisplayClass1_0.<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) --- .../Pipes/IpcClientService.cs | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/dotnetCampus.Ipc/Pipes/IpcClientService.cs b/src/dotnetCampus.Ipc/Pipes/IpcClientService.cs index a3aabeb..0d52d11 100644 --- a/src/dotnetCampus.Ipc/Pipes/IpcClientService.cs +++ b/src/dotnetCampus.Ipc/Pipes/IpcClientService.cs @@ -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; @@ -269,7 +270,7 @@ internal async Task WriteMessageAsync(IpcMessageTracker // 这里的 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 以应对并发场景。 } @@ -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); + } } } From 8417746485b91aa92426cf78b06c6e58e3fbe877 Mon Sep 17 00:00:00 2001 From: lindexi Date: Tue, 9 Jan 2024 15:19:12 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=9B=B4=E6=AD=A3=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dotnetCampus.Ipc/Pipes/IpcClientService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dotnetCampus.Ipc/Pipes/IpcClientService.cs b/src/dotnetCampus.Ipc/Pipes/IpcClientService.cs index 0d52d11..cb4f687 100644 --- a/src/dotnetCampus.Ipc/Pipes/IpcClientService.cs +++ b/src/dotnetCampus.Ipc/Pipes/IpcClientService.cs @@ -328,8 +328,8 @@ await IpcMessageConverter.WriteAsync { // 比如 Pipe is broken. 等异常 tracker.Debug("IPC write fail."); - // 此时无法知道是对方断开了连接,还是其他异常,因此决定这里抛出的是 IpcException 异常 - throw new IpcException($"IPC write fail. Tag={tracker.Tag} LocalClient:'{IpcContext.PipeName}';RemoteServer:'{PeerName}'", e); + // 重新封装异常,让上层可以获取到更多信息,且可以使用 IPC 的异常类型进行判断 + throw new IpcRemoteException($"IPC write fail. Tag={tracker.Tag} LocalClient:'{IpcContext.PipeName}';RemoteServer:'{PeerName}'", e); } } } From 0354f80dd1f9a91162600cf618dd4cf27d264c85 Mon Sep 17 00:00:00 2001 From: lindexi Date: Tue, 9 Jan 2024 15:19:16 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 27d1bb6..07d1a88 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -11,7 +11,7 @@ 本机内多进程通讯库,稳定 IPC 通讯库 git - Copyright © 2020-2023 dotnet campus, All Rights Reserved. + Copyright © 2020-2024 dotnet campus, All Rights Reserved. $(NoWarn);NU1803