-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consolidate common IPC / named pipe code #11546
Consolidate common IPC / named pipe code #11546
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR consolidates common IPC/named pipe functionality across multiple node components by refactoring packet deserialization methods, removing redundant code (including the BufferedReadStream), and updating the underlying pipe abstraction to use NodePipeClient/NodePipeServer.
- Refactored methods for deserializing packets (now DeserializePacket returning INodePacket) across components.
- Replaced direct stream operations with NodePipeClient/NodePipeServer and removed unused ifdef dead code.
- Removed BufferedReadStream to rely on MemoryStream buffering and simplified handshake and connection logic.
Reviewed Changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
src/Build/BackEnd/Client/MSBuildClientPacketPump.cs | Updated to use NodePipeClient; refactored packet read loop to call asynchronous ReadPacketAsync. |
src/Shared/NodePacketFactory.cs | Changed DeserializeAndRoutePacket to DeserializePacket and updated its usage. |
src/Shared/NodeEndpointOutOfProcBase.cs | Updated to use NodePipeServer and simplified handshake/connection logic by replacing obsolete code. |
src/Build/BackEnd/Client/MSBuildClient.cs | Refactored to use NodePipeClient for writing packets and connecting to server. |
Other files | Method renames and refactoring for unified IPC API, along with removal of BufferedReadStream. |
Comments suppressed due to low confidence (3)
src/Shared/NodeEndpointOutOfProcBase.cs:274
- [nitpick] The method WaitForConnection() returns a LinkStatus value but its name does not indicate that it determines the connection status. Consider renaming it or adding documentation to clarify its side effects and return value.
ChangeLinkStatus(localPipeServer.WaitForConnection());
src/Build/BackEnd/Client/MSBuildClient.cs:403
- Verify that the new NodePipeClient.WritePacket method correctly replicates the previous buffering and flushing behavior, ensuring no regression in packet transmission.
_pipeClient.WritePacket(packet);
src/Build/BackEnd/Node/InProcNode.cs:222
- After refactoring to return INodePacket via DeserializePacket, ensure that callers of this method are aware that a null return (as seen in the in-proc node implementation) is an acceptable outcome or handle it appropriately.
ErrorUtilities.ThrowInternalError("Unexpected call to DeserializeAndRoutePacket on the in-proc node.");
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we'd move the code shared between MSBuild and Microsoft.Build into Framework or another common location so it only has to be compiled/loaded from disk/jitted once. We can't always do that but for node comm stuff, we shouldn't ever be in the "one assembly reflection loaded but not hooked up to find the others" scenario.
But we can do that (much) later.
Just ported the relevant changes over from #11448 ( Otherwise this is good to go 👍 |
@SimaTian , could you have a final look please? |
Motivation
The various node components contain a lot of duplicated code related to reading and writing packets, sequencing pipe operations, managing reusable buffers, handling broken connections, etc. along with differing implementations of performance optimizations and buffer reuse.
This PR aims to encapsulate all common logic into a simple API for reading and writing packets in a single call, along with extracting out the pipe connection and handshake logic for use outside of build nodes.
The primary motivation is to allow the RAR-out-of-proc client and server to share the same IPC code with MSBuild, as that must partially live in the Tasks assembly and cannot depend on much of the node provider/endpoint framework. Given that existing IPC logic already has test coverage and continued optimizations, it makes more sense to reuse as much as possible instead of adding (yet another) implementation of pipe communication, unit tests, ect.
Notes
Although I've kept behavior as close as possible, there's a few additional changes here to be noted:
ifdefs
were removed or combined. There is a lot of dead code which appears to be a holdover from Mono or unsupported targets, and can now be reduced to: (Framework, .NET Core, or TaskHost).Begin/End
API and customIAsyncResult
implementation adds a lot of complexity and more compile flags.BufferedReadStream
was removed. as it performs the same function as theMemoryStream
buffering. Likely more inefficiently as well due to the small buffer size (meaning more IO ops on the named pipe). I did not test against the most recent perf optimization here, but I would still expect this to be the case.INodePacketFactory.DeserializeAndRoutePacket()
was split into two methods (which accounts for most of the file changes here). Motivation is soNodePipeBase
can directly return anINodePacket
instance but still allow the caller to decide whether to route it. This is not publicly exposed so it shouldn't be a breaking change.PipeOptions.WriteThrough
. This flag has no effect on local IPC, which will always use kernel buffers.Let me know if there's anything I need to split off to make this more digestible (e.g. INodePacketFactory plumbing, BufferedReadStream removal, some of the flag consolidation would be very quick), but this gives the full context.