Enable contracts for new holders and refactor Crst initialization - #131552
Enable contracts for new holders and refactor Crst initialization#131552AaronRobinsonMSFT wants to merge 2 commits into
Conversation
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @agocke |
There was a problem hiding this comment.
Pull request overview
This PR updates CoreCLR’s contracts and lock initialization patterns to use a more consistent EE contract vocabulary across VM/GC/NativeAOT, and relocates IsIPInModule into the VM while routing debugger usage through EEDebugInterface.
Changes:
- Refactors
CrstStaticinitialization to removeInitNoThrowand update call sites across VM/GC/NativeAOT to callInit. - Introduces
ENABLE_EE_CONTRACTS(when contracts implementation is enabled) and uses it to upgrade holder contracts inholder.h. - Moves
IsIPInModulefromutilcode/util.cppintovm/util.cpp, adds a VM declaration, and exposes it viaEEDebugInterface.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/vm/util.hpp | Declares VM-level IsIPInModule. |
| src/coreclr/vm/util.cpp | Adds VM implementation of IsIPInModule. |
| src/coreclr/vm/eventtrace.cpp | Switches CrstStatic init from InitNoThrow to Init. |
| src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h | Switches EventPipe lock init to Init. |
| src/coreclr/vm/eedbginterfaceimpl.h | Adds IsIPInModule to the EE debugger interface implementation. |
| src/coreclr/vm/eedbginterfaceimpl.cpp | Implements EEDbgInterfaceImpl::IsIPInModule forwarding to the helper. |
| src/coreclr/vm/eedbginterface.h | Adds IsIPInModule to EEDebugInterface. |
| src/coreclr/vm/eecontract.h | Introduces ENABLE_EE_CONTRACTS under ENABLE_CONTRACTS_IMPL. |
| src/coreclr/vm/crst.h | Removes CrstStatic::InitNoThrow and standardizes on Init. |
| src/coreclr/vm/crst.cpp | Changes CrstBase::InitWorker contract and initialization behavior. |
| src/coreclr/vm/common.h | Adjusts include ordering so EE contract vocabulary is visible to holders. |
| src/coreclr/utilcode/util.cpp | Removes the old IsIPInModule implementation from utilcode. |
| src/coreclr/nativeaot/Runtime/GcStressControl.cpp | Updates NativeAOT lock init to Init. |
| src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp | Updates NativeAOT EventPipe locks to Init. |
| src/coreclr/nativeaot/Runtime/Crst.h | Removes NativeAOT InitNoThrow shim. |
| src/coreclr/nativeaot/Runtime/clrgc.enabled.cpp | Updates GC event lock init to Init. |
| src/coreclr/inc/utilcode.h | Removes utilcode declaration of IsIPInModule. |
| src/coreclr/inc/metadata.h | Adds GC_NOTRIGGER to several lock-acquire contract blocks. |
| src/coreclr/inc/holder.h | Uses full CONTRACTL under ENABLE_EE_CONTRACTS for ReleaseHolderTraits::Free. |
| src/coreclr/inc/contract.h | Simplifies gating for ENABLE_CONTRACTS_DATA / ENABLE_CONTRACTS (DAC excluded from impl). |
| src/coreclr/gc/handletable.cpp | Switches handle table lock init to Init and removes failure cleanup path. |
| src/coreclr/gc/env/gcenv.sync.h | Changes GC env shim CrstStatic init API to Init and drops status return. |
| src/coreclr/debug/ee/debugger.cpp | Routes debugger’s module-IP check through g_pEEInterface->IsIPInModule. |
Copilot's findings
Comments suppressed due to low confidence (1)
src/coreclr/vm/crst.cpp:42
- CrstBase::InitWorker relies on
_ASSERTE(suc)afterminipal_mutex_init. In retail builds_ASSERTEcompiles away, so a failed mutex init would still mark the Crst initialized and proceed with an uninitializedm_lock, leading to undefined behavior later. This needs an all-build failure path (fail-fast) rather than a debug-only assert.
_ASSERTE((flags & CRST_INITIALIZED) == 0);
bool suc = minipal_mutex_init(&m_lock._mtx);
_ASSERTE(suc);
- Files reviewed: 23/23 changed files
- Comments generated: 1
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Copilot's findings
Suppressed comments (4)
src/coreclr/vm/crst.cpp:42
- CrstBase::InitWorker ignores minipal_mutex_init failure in retail builds (only _ASSERTE checks it). If initialization fails (e.g., OOM), we proceed with an uninitialized mutex, which can lead to undefined behavior later. This is especially problematic now that callers no longer have an InitNoThrow fallback path.
_ASSERTE((flags & CRST_INITIALIZED) == 0);
bool suc = minipal_mutex_init(&m_lock._mtx);
_ASSERTE(suc);
src/coreclr/gc/env/gcenv.sync.h:32
- CrstStatic::Init now discards the CLRCriticalSection::Initialize() return value, removing even the prior ability to detect initialization failure in debug builds. If Initialize() can fail, this can leave the GC lock in an unusable state with no signal to callers.
void Init(CrstType eType, CrstFlags eFlags = CRST_DEFAULT)
{
(void)m_cs.Initialize();
}
src/coreclr/inc/holder.h:1019
- The body of ReleaseHolderTraits::Free has inconsistent indentation (contract lines and ContractReleaseValidate() are not indented to match the rest of the function body). This makes the block harder to read and stands out from the surrounding style in holder.h.
{
STATIC_CONTRACT_NOTHROW;
STATIC_CONTRACT_GC_TRIGGERS;
STATIC_CONTRACT_MODE_PREEMPTIVE;
#ifdef ENABLE_CONTRACTS_IMPL
ContractReleaseValidate();
#endif // ENABLE_CONTRACTS_IMPL
src/coreclr/vm/eedbginterface.h:136
- New virtual methods on these VM<->debugger interfaces should be appended at the end to preserve vtable slot ordering (per established CoreCLR convention). IsIPInModule is currently inserted in the middle of the interface, which increases ABI risk for components that may be built against a different header version.
virtual BOOL IsManagedNativeCode(const BYTE *address) = 0;
#endif // #ifndef DACCESS_COMPILE
virtual BOOL IsIPInModule(PTR_VOID pModuleBaseAddress, PCODE ip) = 0;
virtual PCODE GetNativeCodeStartAddress(PCODE address) = 0;
virtual MethodDesc *GetNativeCodeMethodDesc(const PCODE address) = 0;
- Files reviewed: 24/24 changed files
- Comments generated: 0 new
|
|
||
| // Indicates that the EE contract vocabulary (GC_TRIGGERS and MODE_COOPERATIVE/PREEMPTIVE/ANY) | ||
| // is available and enforced. | ||
| #define ENABLE_EE_CONTRACTS |
| }; | ||
|
|
||
| #ifdef ENABLE_CONTRACTS_IMPL | ||
| // Out-of-line hook that enforces the ReleaseHolder release-path contract |
There was a problem hiding this comment.
This is fixing the problem with Release holder. How many others are slipping through the cracks?
I think this redefinition of the contract macros
runtime/src/coreclr/vm/eecontract.h
Lines 19 to 20 in ccd6004
Summary
Enables EE contracts for the holder infrastructure and refactors related lock initialization so that a single, consistent contract vocabulary is used across the VM, GC, and NativeAOT runtimes.
Details
inc/contract.h): Simplify the macros that gateENABLE_CONTRACTS_DATA/ENABLE_CONTRACTS. Contract data no longer depends onJIT_BUILD/CROSS_COMPILE; DAC builds continue to reference contract data but not the implementation.inc/holder.h):ReleaseHolderTraits::Freenow uses a fullCONTRACTLblock (NOTHROW/GC_TRIGGERS/MODE_PREEMPTIVE) when the EE contract vocabulary is available, falling back to the static contracts otherwise.vm/eecontract.h): Introduce theENABLE_EE_CONTRACTSdefine to indicate the EE contract vocabulary (GC_TRIGGERS,MODE_COOPERATIVE/PREEMPTIVE/ANY) is available and enforced.CrstStatic::InitNoThrowand makeInit(andCrstBase::InitWorker)NOTHROW/GC_NOTRIGGER. All callers in the VM, GC, and NativeAOT are updated to callInit.gcenv.sync.hand NativeAOTCrst.hdrop theirInitNoThrowshims accordingly.IsIPInModule: Move the implementation out of the genericutilcode/util.cpp(which cannot depend on EE contracts) intovm/util.cpp, declare it invm/util.hpp, and expose it to the debugger through the EE debugger interface (IEEDbgInterface::IsIPInModule) instead of the free function.inc/metadata.h): AddGC_NOTRIGGERto several lock-acquire contracts.vm/common.h): Pull ineecontract.hbeforeholder.hso the EE contract vocabulary is visible to the holder definitions.Note
This PR description was generated with the assistance of GitHub Copilot.