Skip to content

Commit fb32166

Browse files
kotlarmilosCopilot
andcommitted
Add cLockAllowLeak attribute to RSLock and use it on DbgTransportTarget 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>
1 parent 6820c80 commit fb32166

3 files changed

Lines changed: 10 additions & 4 deletions

File tree

src/coreclr/debug/di/dbgtransportmanager.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ DbgTransportTarget::DbgTransportTarget()
7474
// Initialization routine called only by the DbgTransportManager.
7575
HRESULT DbgTransportTarget::Init()
7676
{
77-
m_sLock.Init("DbgTransportTarget Lock", RSLock::cLockFlat, RSLock::LL_DBG_TRANSPORT_TARGET_LOCK);
77+
// The Unix loader does not invoke DbgDllMain DLL_PROCESS_DETACH for mscordbi at process exit,
78+
// so Shutdown() may never run. Mark the lock as allowing leak to skip the destructor assert.
79+
m_sLock.Init("DbgTransportTarget Lock", RSLock::cLockFlat | RSLock::cLockAllowLeak, RSLock::LL_DBG_TRANSPORT_TARGET_LOCK);
7880

7981
return S_OK;
8082
}

src/coreclr/debug/di/rspriv.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,10 @@ class RSLock
716716
// to count this lock in m_cTotalDbgApiLocks, which is asserted to be 0 on entry
717717
// to public APIs. Example of such a lock: LL_SHIM_PROCESS_DISPOSE_LOCK
718718
cLockNonDbgApi = 0x00000004,
719+
720+
// Skip the leak assert in the destructor. Use for static-lifetime locks
721+
// whose owning shutdown path is not guaranteed to run.
722+
cLockAllowLeak = 0x00000008,
719723
};
720724

721725
// To prevent deadlocks, we order all locks.

src/coreclr/debug/di/rspriv.inl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -504,9 +504,9 @@ inline RSLock::RSLock()
504504

505505
inline RSLock::~RSLock()
506506
{
507-
// If this lock is still ininitialized, then no body ever deleted the critical section
508-
// for it and we're leaking.
509-
CONSISTENCY_CHECK_MSGF(!IsInit(), ("Leaking Critical section for RS Lock '%s'", m_szTag));
507+
// If this lock is still initialized, then nobody ever deleted the critical section
508+
// for it and we're leaking. cLockAllowLeak opts out of this assert.
509+
CONSISTENCY_CHECK_MSGF(!IsInit() || (m_eAttr & cLockAllowLeak), ("Leaking Critical section for RS Lock '%s'", m_szTag));
510510
}
511511
#endif
512512

0 commit comments

Comments
 (0)