#52793: fix: don't destroy contentTracing.stopRecording() promise off the UI thread
Merged
Created: Aug 12, 2026, 4:03:00 PM
Merged: Aug 12, 2026, 5:35:51 PM
7 comments
Target: main
Description of Change
Seen as the win-x64 test shard crash in https://github.com/electron/electron/actions/runs/31624457326/job/94214475444 (Cannot replace file '...\trace.json' : FILE_ERROR_EXISTS followed by persistent-node.h:162 Debug check failed: IsCreationThread()).
stopRecording(path): when Chromium'sFileTraceDataEndpointfails to rename the finished trace into place it destroys its completion closure on the thread pool without running it. That closure owns thegin_helper::Promise, which since #51386 is acppgc::Persistentand must die on the creating thread — DCHECK in testing builds, unsynchronized persistent-region mutation in release. Wrap the closure inBindPostTaskToCurrentDefaultso it is run and destroyed on the UI thread either way. (The promise stays pending on that path, as before; the endpoint gives us no failure signal.)StopTracing()dereferenced the optional path before checking it, so a failed temp-file creation would crash instead of rejecting.- Spec: every test attempt now gets its own output file. A timed-out attempt can leave an endpoint still writing to
trace.json; two endpoints finalizing the same path race on the rename, which is how CI reached the failure path above.
Reproduced locally by pointing stopRecording() at a non-empty directory: pre-fix binary dies on the same DCHECK, fixed binary logs the endpoint error and carries on, subsequent sessions still work.
Checklist
- I have built and tested this change
- I have filled out the PR description
- I have reviewed and verified the changes
-
npm testpasses (relevant subset ofapi-content-tracing-spec)
Release Notes
Notes: Fixed a potential crash in contentTracing.stopRecording() when the trace file could not be written to the requested path.
Backports
Semver Impact
Major
Breaking changes
Minor
New features
Patch
Bug fixes
None
Docs, tests, etc.
Semantic Versioning helps users understand the impact of updates:
- Major (X.y.z): Breaking changes that may require code modifications
- Minor (x.Y.z): New features that maintain backward compatibility
- Patch (x.y.Z): Bug fixes that don't change the API
- None: Changes that don't affect using facing parts of Electron