Skip to content

Keep waiting for a per-user task that started between two reads - #122

Open
Laurent Zogaj (26zl) wants to merge 1 commit into
microsoft:mainfrom
26zl:pr/user-task-poll-race
Open

Laurent Zogaj (26zl) wants to merge 1 commit into
microsoft:mainfrom
26zl:pr/user-task-poll-race

Conversation

@26zl

Copy link
Copy Markdown
Contributor

Same background as my other two Uninstall PRs. This one is a timing issue in the per-user task polling that I could only trigger by forcing the timing.

Invoke-DevConfigUnelevatedCommand polls its scheduled task with two separate reads, Get-ScheduledTask for the state and then Get-ScheduledTaskInfo for the result, about 200 ms apart. If the task starts between them, the first read still says Ready while the second already reports 0x41301 (SCHED_S_TASK_RUNNING). That flips $hasStarted, the loop condition checks the stale state, and the loop exits with the task still running: the function returns 267009 as the exit code with an empty output, the cleanup step is flagged as failed, and the finally block stops the task, killing the uninstaller mid-run.

The fix treats 0x41301 as "still running" in the loop condition. The opposite order (task finishes between the reads) already works, because the state read says Running.

Reproduced on Windows 11 Pro 25H2 (build 26200.9550), pwsh 7.6.6, with the real function and a temporary task under my own user, with Start-ScheduledTask wrapped so the task starts between the two reads. Before: ExitCode=267009, empty output, Stop-ScheduledTask called on the running task. After: ExitCode=0, output fine, no stop. On an idle machine the task is running well within the loop's initial 500 ms sleep, so 20 unforced runs never hit the window here; it opens when the scheduler is slower than that, and an Uninstall starts one such task per per-user package.

Only src/ is touched; the signed copy is left to the sign pipeline.

Thanks for having a look.

Invoke-DevConfigUnelevatedCommand polls the task with two separate
reads: Get-ScheduledTask for the state, then Get-ScheduledTaskInfo for
the result. If the task starts between them, the first read still
says Ready while the second already reports 0x41301
(SCHED_S_TASK_RUNNING). $hasStarted flips, the state is not Running,
the loop exits, 267009 is returned as the command's exit code, and the
finally block stops the task that is still uninstalling. Treat 0x41301
as "still running" in the loop condition.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant