-
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
Implement out-of-proc RAR node lifecycle #11383
base: main
Are you sure you want to change the base?
Conversation
Would you be able to separate the pure code moves and actual code changes? It's fine to keep all in a single PR, but separate commits would be great. It'll help speed up and focus the reviews. |
e41a063
to
4ba973c
Compare
FYI I'm separating the code moves (named pipe / IPC stuff) into another PR since I've been further consolidating the IPC code that's duplicated across all node implementations, and that's a bit more risk given the different code paths for the APM and TPL-based versions due to .NET 3.5 compat for the TaskHost. Will be updating the main work item with the overall design / ordering of PRs so it helps to see where this is going, since there's still ~5 or so main components after this. But that should be the only real code move / refactoring required for the whole project. |
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.
So to sum up, we're moving the communication stuff into a common section for communicating nodes and then creating a new type of node.
Looks fine to me.
@@ -3420,6 +3426,21 @@ private static void StartLocalNode(CommandLineSwitches commandLineSwitches, bool | |||
OutOfProcTaskHostNode node = new OutOfProcTaskHostNode(); | |||
shutdownReason = node.Run(out nodeException); | |||
} | |||
else if (nodeModeNumber == 3) |
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.
future proofing: when does it become a good time to switch to a switch, given the increasing number of node types?
|
||
internal static NamedPipeServerStream CreateSecurePipeServer(string pipeName, int maxNumberOfServerInstances = 1, int pipeBufferSize = DefaultPipeBufferSize) | ||
{ | ||
#if FEATURE_PIPE_SECURITY && FEATURE_NAMED_PIPE_SECURITY_CONSTRUCTOR |
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.
Would it be reasonable to refactor this in a manner that doesn't use interwoven #if directives or would it lead to too many branches? (and if so, maybe some more shuffling could help?)
In an IDE it will probably be somewhat more readable, however as-is it is tad clunky to parse what happens when.
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.
Yup I'm about to put out a separate PR with the pipe communication refactor on its own. I did a pass through the flags and consolidated it down to FEATURE_PIPEOPTIONS_CURRENTUSERONLY and TASKHOST. The gist is that NETCore has the CurrentUserOnly
flag which lets us skip manually validating the user, And since Mono is no long targeted, the Full Framework bits will always run on Windows.
Most of these flags were either redundant or guarding against scenarios no longer supported.
There are some minor conflicts, probably due to the perf work from @Erarndt we recently merged. |
8614613
to
3fd7cc6
Compare
Relevant changes are in second commit - I just rebased on the active IPC pr since this depends on it. |
31b7991
to
7dabf6a
Compare
Kk since the IPC stuff got merged, this is also good to go other than this compile error I hit after rebasing:
I think this is from the change which swapped It seems like referencing
Anything that can be done to resolve this? Ideally I would have access to Otherwise the simplest thing would to swap |
Context
This implements the full node lifecycle and execution flow for an out-of-proc RAR node via an additional
nodemode
. This does not yet execute the RAR task itself, or serialize anything other than empty dummy payloads - enabling the feature will only run a test message and then fall back to in-proc execution.Changes Made
New RAR nodemode
$env:MSBuildRarNode=1
conditions theRarNodeLauncher
to create a new instance ofmsbuild.exe /nodemode:3
. This runs a persistent out-of-proc RAR node which can receive serialized requests from a RAR task client in another process, execute the task, and serialize back the outputs.Conditioning execution
EngineServices.IsOutOfProcRarNodeEnabled
tells the RAR task whether to run out-of-proc. This is necessary since we want the task to avoid trying to connect to the node if MSBuild was launched without the flag enabled, which can differ between builds. This is not easily achieved via environment variables due to node reuse.ResolveAssemblyReferencesOutOfProcess
can be used to exclude a specific target from running out-of-proc.RAR Out-Of-Proc Node
RAR Out-Of-Proc Client
BuildEngine
. This ensures that we don't pay overhead cost of reconnecting / repeating handshakes for every task, while still disposing of the client between builds to prevent an idle reused MSBuild node from holding on to a server instance.Testing
You can validate the feature is functional by setting
$env:MSBuildRarNode=1
and checking tracing logs + active processes. Untested code is mostly glue and orchestrating pipe connections. The most brittle code (IPC / serialization) already has test coverage from other MSBuild node implementations.Notes