Skip to content

fix: prevent shutdown deadlocks and logger races - #938

Open
Adiker wants to merge 1 commit into
SteamClientHomebrew:mainfrom
Adiker:codex/shutdown-safety
Open

Adiker wants to merge 1 commit into
SteamClientHomebrew:mainfrom
Adiker:codex/shutdown-safety

Conversation

@Adiker

@Adiker Adiker commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Steam can hang or crash during normal exit or a restart after changing the interface language. Shutdown may run after function-local services have been destroyed, and CDP callbacks can still be waiting for replies from an exiting browser. Plugin IPC threads also write log buffers while MEP clients read them.

  • Keep the lifecycle gates and shutdown-used MEP services alive until process exit, so backend teardown can notify gates and unregister listeners safely.
  • Fail pending CDP requests before joining workers. Check shutdown and register requests under the same mutex, preventing a concurrent sender from inserting an unresolved request after the shutdown drain.
  • Synchronize plugin log buffers and file writes. Replace the mutable shared logger vector with synchronized get-or-create and snapshots, retain logger ownership through late teardown, and use thread-safe local time conversion. Invoke log listeners outside the buffer and registry locks so they can collect logs or log again.
  • Add nine regression cases covering return/exit/explicit-stop lifecycle paths, blocked and concurrent CDP requests, concurrent buffer/registry access, and reentrant log listeners.

Related work

Related to #931. The shutdown lifetime changes and the CDP callback join ordering partially overlap draft #841; this PR brings the tested shutdown work together independently of the macOS restoration, and additionally fixes request registration and logger races. This is not confirmation of the exact cause on the issue reporter's machine.

The per-plugin zombie-reaping delay fix is separate in #937. This PR targets main directly and does not include that change.

Validation

  • Against unmodified current main, both return/exit lifecycle cases time out and the blocked-CDP-callback case fails its watchdog; the same cases pass after the fix.
  • Nine regression cases pass on this branch in a 32-bit Linux Debug build with -Wall -Wextra -Werror.
  • The same nine cases pass in a 64-bit ASan/UBSan build without reports.
  • All three logger cases also pass under ThreadSanitizer without reports.
  • Live Linux testing used Millennium 3.6.1 with these production changes and, subsequently, the separate fix(posix): reap exited plugin children during shutdown #937 change: two consecutive exit cycles completed successfully with Millennium unloaded successfully and no new Steam coredumps. These were combined-package tests, not a new full Steam run from this branch alone.

Each suite also runs independently, for example:

cmake -S tests/cpp/cdp_shutdown -B build/cdp-shutdown -DCMAKE_BUILD_TYPE=Debug
cmake --build build/cdp-shutdown --parallel 1
ctest --test-dir build/cdp-shutdown --output-on-failure

Use tests/cpp/posix_lifecycle or tests/cpp/logger_concurrency for the other suites.

This branch has not been deployed

No deployments
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