Restore mutex-protected worker shutdown tracking - #679
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #679 +/- ##
==========================================
+ Coverage 77.78% 77.79% +0.02%
==========================================
Files 118 118
Lines 14332 14361 +29
==========================================
+ Hits 11147 11172 +25
- Misses 3185 3189 +4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR fixes an intermittent thread_pool::join() stall by restoring a mutex-ordered shutdown predicate based on a live-worker set, eliminating a lost-wakeup window that could leave timed joins sleeping until their deadline even after all workers had exited (Issue #678).
Changes:
- Replace the atomic “workers running” counter with a mutex-protected live
workersset and useworkers.empty()as the shutdown/join predicate. - Make worker/thread registration rollback-safe and keep explicit
std::thread::join()behavior. - Add a regression test that repeatedly exercises timed idle-worker shutdown, and document the user-visible fix in the 2.2.0 release notes.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/be20_api/threadpool.h | Introduces a mutex-protected live-worker set to serve as the authoritative shutdown predicate. |
| src/be20_api/threadpool.cpp | Implements mutex-ordered worker registration/removal and updates join predicates to use workers.empty(). |
| src/be20_api/test_be20_threadpool.cpp | Adds a repeated timed-join regression test to detect the prior idle-worker shutdown stall. |
| doc/RELEASE_NOTES.md | Documents the shutdown/join stall fix as a user-visible change for 2.2.0. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Summary
std::thread::join()calls and make worker/thread registration rollback-safev2.2.0beta2release candidate tracked in release: v2.2.0beta2 #680Root cause
The atomic
workers_runningcounter was changed and followed by a condition-variable notification without holding the mutex used bythread_pool::join(). With multiple workers exiting, the last notification could occur after the join predicate was checked but before the joining thread actually slept. The counter could then be zero with no future notifier, leaving the timed join asleep until its deadline.The restored worker set closes that window because worker removal and
workers.empty()are ordered by the same mutex used byTO_MAIN.Addresses #678.
Validation
make -C src check TESTS=test_be20_api— passmake check— pass (4/4 test programs; 0 failures, 0 errors)make distcheck— pass (clean archive build, install/uninstall, and 4/4 test programs)cbc2cc994d9b47330e27b582947e9a40d82c738b, including macOS, Ubuntu, AddressSanitizer, Windows runtime, MinGW, Codecov, documentation, Snap, and CodeQLcbc2cc994d9b47330e27b582947e9a40d82c738b; 5/5 changed files reviewed with no new comments and no review threadsBeta test release
The signed, reviewed open-PR head is published as
v2.2.0beta2.PR #679 remains open and unmerged while beta feedback is collected.