A collection that fails once the session has been granted - most plausibly
the target exiting before the stop command reaches it - left the task copying
the trace connection behind. That connection is torn down on the way out, the
copy faults, nobody awaits it, and the finalizer hands it to
TaskScheduler.UnobservedTaskException, which this app reports as a crash: a
second report of a failure the dialog's error bar had already explained
correctly, minutes later and detached from the gesture that caused it. The
CollectTracing2 fallback walks the same path, so one dying target produced two
of them.
The teardown order is the substance of the fix. The session connection has to
go first, because after the failure nothing else will ever end the read the
copy is parked on; the drain second, so that its own failure is observed
rather than abandoned; and the half-copied trace last, so nothing is still
writing into it when it is dropped.
The regression test pins the invariant rather than the symptom, because the
symptom is transport-specific: a Windows named pipe reports an aborted
overlapped read as cancellation, and a cancelled task is never unobserved, so
only the unix transport can produce the crash at all. What holds everywhere is
that no drain may still be running once the failure path is done with it.
Assisted-by: Claude:claude-opus-5:Claude Code