Do not respect NodeReuse for TaskHosts Fixes #3141#5144
Do not respect NodeReuse for TaskHosts Fixes #3141#5144Forgind merged 24 commits intodotnet:masterfrom
Conversation
They can lock the node, causing errors.
rainersigwald
left a comment
There was a problem hiding this comment.
Can you add a regression test? Maybe a test task that returns its PID, and validate that that PID is not alive at the end of the build?
src/MSBuild/OutOfProcTaskHostNode.cs
Outdated
| ErrorUtilities.VerifyThrow(!_isTaskExecuting, "We should never have a task in the process of executing when we receive NodeBuildComplete."); | ||
|
|
||
| _shutdownReason = buildComplete.PrepareForReuse ? NodeEngineShutdownReason.BuildCompleteReuse : NodeEngineShutdownReason.BuildComplete; | ||
| _shutdownReason = NodeEngineShutdownReason.BuildComplete; |
There was a problem hiding this comment.
Worth a comment that there's no reuse scenario here because ...
|
Wouldn't this slow down people whose builds call into out of proc task nodes many times? An escape hatch might be useful. I guess it depends which population is larger, the repos with frequently called out of proc tasks, or the repos that build their own tasks. Probably the later ... |
|
I could add an escape hatch. I also considered trying to detect if the relevant task was a custom task or MSBuild task, but it got a little too complicated. |
| </Target> | ||
| </Project>"; | ||
| TransientTestFile project = env.CreateFile("testProject.csproj", pidTaskProject); | ||
| MockLogger logger = new MockLogger(); |
There was a problem hiding this comment.
| MockLogger logger = new MockLogger(); | |
| MockLogger logger = new MockLogger(_output); |
src/Shared/Traits.cs
Outdated
| public readonly bool UseSymlinkTimeInsteadOfTargetTime = Environment.GetEnvironmentVariable("MSBUILDUSESYMLINKTIMESTAMP") == "1"; | ||
|
|
||
| /// <summary> | ||
| /// Allow node reuse on TaskHost nodes. This breaks if there are custom tasks. |
There was a problem hiding this comment.
| /// Allow node reuse on TaskHost nodes. This breaks if there are custom tasks. | |
| /// Allow node reuse of TaskHost nodes. This results in task assemblies locked past the build lifetime, but may improve performance. |
| using System.IO; | ||
| using System.Linq; | ||
| using System.Text.RegularExpressions; | ||
| using Microsoft.Build.UnitTests; |
There was a problem hiding this comment.
Move unrelated edit to a new PR or just revert.
|
|
||
| [Fact] | ||
| [SkipOnTargetFramework(TargetFrameworkMonikers.Netcoreapp, "https://github.com/microsoft/msbuild/issues/5158")] | ||
| public void TaskNodesDieAfterBuild() |
There was a problem hiding this comment.
Why is this test in this class? It's not about warnings-as-messages. Can you find a better home, like maybe a new TaskHostFactory_Tests?
| int start = logger.FullLog.IndexOf(introToPID) + introToPID.Length; | ||
| int length = logger.FullLog.IndexOf(afterPID) - start; | ||
| string pid = logger.FullLog.Substring(start, length); |
There was a problem hiding this comment.
Instead of grepping through the logging, can you change the test to return the PID of its process as a property, capture the property into a named property when you call it, and read the property out of the built project instance? That's a much cleaner way to do things (and a good exercise for you in using our API).
rainersigwald
left a comment
There was a problem hiding this comment.
Sorry, misclick on previous review.
| @@ -0,0 +1,38 @@ | |||
| using System; | |||
| public class ProcessIdTask : Task | ||
| { | ||
| [Output] | ||
| public Int32 pid { get; set; } |
There was a problem hiding this comment.
| public Int32 pid { get; set; } | |
| public int Pid { get; set; } |
style nits: use the C# type where possible, and properties should start with a capital letter.
| public sealed class TaskHostFactory_Tests | ||
| { | ||
| [Fact] | ||
| [SkipOnTargetFramework(TargetFrameworkMonikers.Netcoreapp, "https://github.com/microsoft/msbuild/issues/5158")] |
There was a problem hiding this comment.
Does Mono support out-of-proc task hosts? I was going to find out with the automated tests.
This will indicate if we're using a TaskHostNode as expected in the new test.
Todo: investigate failure
| Should.Throw<ArgumentException>(() => Process.GetProcessById(pid)); | ||
| try { | ||
| Process taskHostNode = Process.GetProcessById(pid); | ||
| taskHostNode.WaitForExit(2000); |
There was a problem hiding this comment.
Assert that this reported that the process ended (and didn't time out).
There was a problem hiding this comment.
That's caught by the Should.Throw immediately afterwards. If it times out, Process.GetProcessById won't throw, and the test will fail.
There was a problem hiding this comment.
Not necessarily though, given PID reuse.
| catch (Exception e) | ||
| { | ||
| e.ShouldBeOfType<ArgumentException>(); | ||
| } |
There was a problem hiding this comment.
We want taskHostNode to die. If it dies before this try statement, Process.GetProcessById will throw an ArgumentException, so this test succeeded if either the Should.Throw statement succeeds or the node dies fast, and Process.GetProcessById throws an ArgumentException.
There was a problem hiding this comment.
Comment with that reasoning, catch only the exact exception, minimize the scope of the catch, and can you assert details of it?
|
Checked with @rainersigwald, and this does not work on mono, so disabling the test seems reasonable. |
In some offline discussion, @jaredpar pointed out that the TaskHostFactory docs didn't specify that the TaskHost node wouldn't live on past the build. It has since 16.6 (dotnet/msbuild#5144), so document that.
They can lock the node, causing errors.
Resolves #3141.