[clr-interp] Skip RSLock leak assert for DbgTransportTarget on Unix#127754
Conversation
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
There was a problem hiding this comment.
Pull request overview
This PR adds a defensive DbgTransportTarget destructor so the right-side debug transport can clean up its lock and tracked sessions during static destruction, covering Unix teardown paths where DbgDllMain(DLL_PROCESS_DETACH) may not run.
Changes:
- Declares an explicit destructor for
DbgTransportTarget. - Adds destructor logic that calls
Shutdown()when the transport lock appears initialized. - Keeps the fix localized to the debug transport manager used by the CoreCLR debugger transport layer.
Show a summary per file
| File | Description |
|---|---|
src/coreclr/debug/di/dbgtransportmanager.h |
Declares the new DbgTransportTarget destructor. |
src/coreclr/debug/di/dbgtransportmanager.cpp |
Implements the destructor and conditionally invokes Shutdown() during static destruction. |
Copilot's findings
- Files reviewed: 2/2 changed files
- Comments generated: 1
48c8e47 to
e964c1c
Compare
|
As @janvorli noted, this is nice-to-have. The tests are intended to run primarily against release where the assert does not fire, so this only cleans up checked-build noise. The downside is that the order in which destructors of statics are executed is undefined, so one destructor can easily depend on something that was already destroyed by another. |
|
I would prefer fixing the issue by not using a static instance of the DbgTransportTarget instead. When the However, I can see that @AaronRobinsonMSFT has introduced this static destructor recently and removed dynamic allocation of the transport, so I'd like to know his opinion first. |
This was a simplification. I didn't add an explicit destructor for all the reasons we already know. We really should address the use of |
I agree that completely eliminating the DbgDllMain dependency would be a nicer resolution, but if that isn't straightforward I think we'd be fine allowing the leak. Typical debugger behavior loads DBI and never unloads it until process exit so any missed static cleanup from our code is likely backstopped by OS process cleanup. |
e964c1c to
f82fd15
Compare
…et lock The static g_DbgTransportTarget instance is destroyed after the host process's main() returns. On Unix the dynamic loader does not invoke DbgDllMain DLL_PROCESS_DETACH for mscordbi, so DbgTransportTarget::Shutdown() may never run and the embedded RSLock m_sLock is left initialized at static destruction. The RSLock destructor then asserts on the leak in checked builds and the host aborts with exit 134, marking otherwise successful debugger tests as failures. Add a new cLockAllowLeak bit to RSLock::ELockAttr. The destructor honors it by suppressing the leak assert. Init the DbgTransportTarget lock with this bit set to opt out of the assert, with a comment that the missing Shutdown call on Linux is technically a bug tracked separately as low priority. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
f82fd15 to
fb32166
Compare
|
Add a new RSLock attribute cLockAllowLeak update ~RSLock so the existing CONSISTENCY_CHECK_MSGF leak assert is bypassed when cLockAllowLeak is set. |
Description
The static
g_DbgTransportTargetinstance is destroyed after the host process'smain()returns. On Unix (desktop interpreter) the dynamic loader does not invokeDbgDllMain(DLL_PROCESS_DETACH)formscordbi.dylib, soDbgTransportTarget::Shutdown()may never run and the embeddedRSLock m_sLockis left in its initialized state. In debug builds theRSLockdestructor asserts that the lock wasDestroy()'d before destruction, so the host process aborts.Implementation
The shutdown path can't be made reliable on Unix without changes outside
mscordbi, so the fix opts the lock out of the destructor assert instead of trying to release it:RSLockattributecLockAllowLeak(src/coreclr/debug/di/rspriv.h) for static-lifetime locks whose owning shutdown path is not guaranteed to run.~RSLock()(src/coreclr/debug/di/rspriv.inl) so the existingCONSISTENCY_CHECK_MSGFleak assert is bypassed whencLockAllowLeakis set; behavior for all other locks is unchanged.DbgTransportTarget::m_sLockwithcLockFlat | cLockAllowLeak(src/coreclr/debug/di/dbgtransportmanager.cpp) so the static instance no longer trips the assert when destructed aftermain()returns.Test impact
Locally on osx-arm64
Debugger.Tests --clrinterpreterthe xunit fail count drops from 230 to 65:Inspection.BasicInspection,Inspection.EnumNames,Inspection.GenericInterfaces,Inspection.GenericSharedStatic,Inspection.GenericStatics,Inspection.NestedGenerics,Inspection.inspect_SetVarsStackwalking.ClrMethodsStepping.setIPTestwithUnvaildPos,Stepping.stepin,Stepping.stepoverAsync.AsyncStepInto