MarshallOfSound

#52888: fix: don't let pending shell operations block app exit on Windows

Merged
Created: Aug 17, 2026, 12:20:07 AM
Merged: Aug 17, 2026, 3:11:50 AM
5 comments
Target: main

Description of Change

Fixes #52141 (the crash cases > "promise-destroy-crash" flake on Windows), which turned out to be a real quit hang rather than a test problem.

  • shell.openExternal() / shell.openPath() / shell.showItemInFolder() post their ShellExecuteEx() work to a COM STA thread-pool task with the default SKIP_ON_SHUTDOWN behaviour. A SKIP_ON_SHUTDOWN task that has already started blocks ThreadPoolInstance::Shutdown(), and ShellExecuteEx() can block inside the OS for as long as Windows is showing UI for the request — e.g. the "you'll need a new app to open this link" dialog for a scheme with no registered handler (its helper thread sits in a synchronous cross-process COM release into OpenWith.exe until the dialog is dismissed). Net effect: app.quit() fires will-quit/quit, then the browser main thread parks in TaskTracker::CompleteShutdown() and the process never exits until the user clicks OK.
  • Post these tasks with CONTINUE_ON_SHUTDOWN instead. This matches Chrome's platform_util::OpenItem, which uses that trait for exactly this reason ("can hang shutdown without this trait as it may result in an interactive dialog"). The tasks only touch their bound arguments and OS APIs, so letting shutdown proceed while one is still blocked in the shell is safe.

Verified on Windows CI by looping the promise-destroy-crash fixture with native stack capture on hang: current behaviour hung 132/243 runs (main thread in TaskTracker::CompleteShutdown, worker in ShellExecuteExW → CShellExecute::_RunThreadMaybeWait, shell helper thread in combase!RemoteReleaseRifRef); with this change 0/243.

Checklist

Release Notes

Notes: Fixed an issue on Windows where the app process could fail to exit after app.quit() while a shell.openExternal() or shell.openPath() call was still waiting on a system "Open with" dialog.

Backports

41-x-y
Merged
PR Number
#52899
Merged At
Aug 17, 2026, 5:06:39 AM
Released In
Not yet
Release Date
Not yet
42-x-y
Merged
PR Number
#52900
Merged At
Aug 17, 2026, 8:31:18 AM
Released In
Not yet
Release Date
Not yet
43-x-y
Merged
PR Number
#52897
Merged At
Aug 17, 2026, 4:45:01 AM
Released In
Not yet
Release Date
Not yet
44-x-y
Merged
PR Number
#52898
Merged At
Aug 17, 2026, 4:57:35 AM
Released In
v44.0.0-beta.5
Release Date
Aug 17, 2026, 3:01:12 PM

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