dotnet / dotnet/msbuild

TaskBuilder should force Reacquire when a task finishes while yielded

Open
#13,531 1 comment 0 reactions 0 assignees View on GitHub
Area: Engine backlog triaged
Dominant language
C#
Stars
5.5k
Forks
1.5k
Avg merge
1d 8h
Merged PRs (30d)
141

Description

### Context

`TaskHost` tracks yield state via `_yieldThreadId` (`TaskHost.cs:106`), and `Yield()` verifies you are not already yielded (`TaskHost.cs:361`), but there is **no enforcement after `Execute()` returns**. If a third-party task calls `IBuildEngine3.Yield()` and returns from `Execute()` without calling `Reacquire()`:

1. `RequestBuilder.Yield()` sets `_blockType = Yielded` and tells the engine the entry is `Waiting`
2. The task returns normally - the builder thread **never blocks** (it never reaches the `WaitHandle.WaitAny` in `Reacquire()`)
3. The engine may activate another builder since the entry appears to be `Waiting`
4. The original builder thread continues through the rest of `TargetBuilder` -> `BuildTargets` returns

This is a protocol violation by the task, but the engine should defend against it.

### Proposal

After `taskExecutionHost.Execute()` returns in `TaskBuilder.ExecuteInstantiatedTask` (`TaskBuilder.cs:832`), check whether the task left the node in a yielded state (via `TaskHost._yieldThreadId != -1`) and if so, force a `Reacquire()` before continuing. This would:

- Restore the engine one-active-builder invariant
- Log a warning so task authors can fix their code
- Prevent any downstream issues from the inconsistent state

### Affected code

- `TaskBuilder.cs:832` - after `taskResult = taskExecutionHost.Execute()`
- `TaskHost.cs:106` - `_yieldThreadId` field (currently private, would need to be exposed or checked via a property)

### Why this matters

The engine scheduling correctness depends on the invariant that only one builder is active per node at a time. A yield-without-reacquire silently breaks this invariant. Currently the only defense is that all built-in tasks use `try/finally` around `Yield()/Reacquire()` (`ToolTask.cs:957-1027`, `Unzip.cs:104-166`, `ZipDirectory.cs:78-146`), but third-party tasks have no such guarantee.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.