Fix shared ptr circular reference leaks#40480
Conversation
Co-authored-by: Copilot <copilot@github.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses a thread/lifetime ownership cycle in the Windows-side telemetry loggers that could prevent destruction and lead to leaked threads/resources over long uptimes (as reported in #40470). It removes shared_from_this() captures from the worker thread lambdas so the logger objects can be torn down normally.
Changes:
- Remove
std::enable_shared_from_thisinheritance fromGuestTelemetryLoggerandDmesgCollector. - Change worker thread lambdas to capture
thisinstead of ashared_ptrto self, breaking the circular ownership.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/windows/service/exe/GuestTelemetryLogger.h | Drops enable_shared_from_this inheritance to avoid self-owning patterns. |
| src/windows/service/exe/GuestTelemetryLogger.cpp | Updates worker thread capture from shared_from_this() to this to break the ref cycle. |
| src/windows/common/Dmesg.h | Drops enable_shared_from_this inheritance for the collector. |
| src/windows/common/Dmesg.cpp | Updates dmesg worker thread capture from shared_from_this() to this to break the ref cycle. |
Comments suppressed due to low confidence (1)
src/windows/service/exe/GuestTelemetryLogger.cpp:83
- The worker thread treats shutdown as an exception path:
helpers::ConnectPipethrowsE_ABORTwhen any exit event is signaled (includingm_threadExitfrom the destructor). WithCATCH_LOG()this will be logged as an error even though it’s expected during teardown; consider catching explicitly and suppressing/logging-at-debug whenwil::ResultFromCaughtException() == E_ABORT(similar to DmesgCollector’s handling).
}
}
CATCH_LOG()
});
OneBlue
left a comment
There was a problem hiding this comment.
This change makes sense to break the reference cycle, but that means that this can now be deleted while the worker threads are still running.
If we want to make this change, we need to synchronize the worker threads with the deletion of the instance that they reference (the easiest way would be for both class to keep track of their worker threads, and signal their threads to exit + wait for them to actually exit in the destructor)
|
Yeah that could work, although I would have a preference for synchronizing the thread exit with the VM exit, since that would guarantee that we're not leaking threads (and in the past runaway threads have caused various issues) |
|
Hi @OneBlue , @JohnMcPMS . Both logger's destructor will break and join the thread. I don't think delete this would cause a lifecycle problem. WSL/src/windows/common/Dmesg.cpp Lines 33 to 45 in 4ee7881 |
OneBlue
left a comment
There was a problem hiding this comment.
Hi @OneBlue , @JohnMcPMS . Both logger's destructor will break and join the thread. I don't think delete this would cause a lifecycle problem.
That's true ! I assumed that the thread never exited since the original issue mentioned the thread being leaked, but that was actually because of the circular reference causing the logger itself to never be torn down.
Sorry for the incorrect review, change LGTM !
Summary of the Pull Request
Both loggers have their member thread holding a shared pointer of themselves. This renders the m_exitEvents logic useless. And could lead to resource leaks.
Since the thread's lifespan is always shorter than the logger's, changing the capture from shared_from_this to this will fix the leak.
PR Checklist
Detailed Description of the Pull Request / Additional comments
Validation Steps Performed