Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Migrate SafeComHolder and utilcode holders to LifetimeHolder - #130316

#130316
Merged
AaronRobinsonMSFT merged 11 commits into
dotnet:maindotnet/runtime:mainfrom
AaronRobinsonMSFT:safecomholderpreemp-lifetimeAaronRobinsonMSFT/runtime:safecomholderpreemp-lifetimeCopy head branch name to clipboard
Jul 8, 2026
Merged

Migrate SafeComHolder and utilcode holders to LifetimeHolder#130316
AaronRobinsonMSFT merged 11 commits into
dotnet:maindotnet/runtime:mainfrom
AaronRobinsonMSFT:safecomholderpreemp-lifetimeAaronRobinsonMSFT/runtime:safecomholderpreemp-lifetimeCopy head branch name to clipboard

Conversation

@AaronRobinsonMSFT

@AaronRobinsonMSFT AaronRobinsonMSFT commented Jul 7, 2026

Copy link
Copy Markdown
Member

Continues the incremental migration of CoreCLR's legacy Wrapper / SpecializedWrapper-based RAII holders to the trait-based LifetimeHolder<Traits> pattern.

This PR covers the COM SafeComHolder family and the utilcode loader-heap holders:

  • ComHolderPreemp<T>LifetimeHolder<ComHolderPreempTraits<T>>. Free releases the COM interface in preemptive mode via SafeReleasePreemp (NULL-safe).
  • Convert clearly-preemptive SafeComHolder sites to ComHolderPreemp. These call sites destruct their holder while the thread is in preemptive mode (enclosing function is MODE_PREEMPTIVE, or the holder is scoped after a GCX_PREEMP), so they can use the preemptive-only release path and avoid the coop→preempt bounce in SafeRelease.
  • SafeComHolderComHolderAnyMode (mode-agnostic). ComHolderAnyModeTraits::Free() runs under MODE_ANY and calls SafeRelease, which transitions to preemptive internally when required.
  • utilcode loader-heap holders (ReservedMemoryHolder, ThunkMemoryHolder) migrated to LifetimeHolder traits. Sites that previously called SuppressRelease() and kept using the pointer are split into a raw BYTE* value plus a holder that owns the memory purely as an error-path guard, relinquishing ownership via Detach() on success. Added a NULL guard to ReleaseAllocatedThunks since LifetimeHolder always invokes the trait's Free() on destruction.

Call sites are updated for the LifetimeHolder API throughout: copy-initialization from NULL / a raw pointer becomes default- or brace-initialization; SuppressRelease() / GetValue() become Detach(); IsNull() becomes a nullptr comparison; Extract/Clear/Release become Detach/Free; and an explicit (void**) cast is added where operator& is passed to a void** out-parameter.

Note

This PR description was generated with assistance from GitHub Copilot.

AaronRobinsonMSFT and others added 5 commits July 2, 2026 10:51
Continues the migration of legacy `Wrapper`/`SpecializedWrapper`-based
RAII holders to the trait-based `LifetimeHolder<Traits>` pattern.

`SafeComHolderPreemp<T>` becomes `LifetimeHolder<SafeComHolderPreempTraits<T>>`,
whose `Free` releases the COM interface in preemptive mode via
`SafeReleasePreemp` (NULL-safe). Call sites are updated for the
`LifetimeHolder` API: copy-initialization from `NULL`/a raw pointer
becomes default- or brace-initialization, `SuppressRelease()`/`GetValue()`
become `Detach()`, and `IsNull()` becomes a `nullptr` comparison.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
These call sites destruct their holder while the thread is in preemptive
mode (either the enclosing function is MODE_PREEMPTIVE, or the holder is
declared after a GCX_PREEMP / before a scoped GCX_COOP that reverts), so
they can use the preemptive-only release path without the coop->preempt
bounce performed by SafeRelease.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the SpecializedWrapper-based SafeComHolder with a mode-agnostic
SafeComHolderAny built on LifetimeHolder. The SafeComHolderAnyTraits Free()
runs under MODE_ANY and calls SafeRelease, which transitions to preemptive
internally when required.

Rename all call sites, drop legacy = NULL initializers, translate the old
Extract/SuppressRelease/Clear/Release API to Detach/Free, and add an explicit
(void**) cast where operator& is passed to a void** out-parameter.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the SpecializedWrapper-based ReservedMemoryHolder and ThunkMemoryHolder
with LifetimeHolder traits. Because these sites called SuppressRelease() and
then continued to use the pointer value (which LifetimeHolder's Detach() clears),
split each site into a raw BYTE* value plus a holder that owns the memory purely
as an error-path guard, relinquishing ownership via Detach() on success.

Add a NULL guard to ReleaseAllocatedThunks since LifetimeHolder always invokes
the trait's Free() on destruction.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates CoreCLR native RAII usage by migrating legacy Wrapper/SpecializedWrapper COM + utilcode loader-heap holders to the trait-based LifetimeHolder<Traits> pattern, and adjusts call sites to the new holder API (Detach, Free, etc.).

Changes:

  • Replace legacy SafeComHolder* wrappers with SafeComHolderAny / SafeComHolderPreemp implemented via LifetimeHolder traits.
  • Update COM interop call sites to use LifetimeHolder APIs (Detach, Free) and pointer comparisons (!= nullptr).
  • Migrate utilcode loader-heap holders to LifetimeHolder traits and refactor ownership/guard patterns to avoid SuppressRelease() usage.
Show a summary per file
File Description
src/coreclr/vm/wrappers.h Defines SafeComHolderAny/SafeComHolderPreemp as LifetimeHolder-based traits.
src/coreclr/vm/weakreferencenative.cpp Updates weak-ref QCalls to use SafeComHolderPreemp and Detach patterns.
src/coreclr/vm/stubmgr.cpp Switches COM holders to mode-agnostic SafeComHolderAny.
src/coreclr/vm/stubhelpers.cpp Uses SafeComHolderAny and Detach() for COM interface ownership transfer.
src/coreclr/vm/stdinterfaces.cpp Converts various COM holders to SafeComHolderAny/SafeComHolderPreemp and replaces SuppressRelease() with Detach().
src/coreclr/vm/runtimecallablewrapper.cpp Replaces legacy holders with SafeComHolderAny/SafeComHolderPreemp and updates ownership flows to Detach/Free.
src/coreclr/vm/peimage.cpp Migrates metadata COM holder to SafeComHolderAny.
src/coreclr/vm/peassembly.cpp Migrates metadata emit holder to SafeComHolderAny.
src/coreclr/vm/olevariant.cpp Updates COM holders in OLE variant marshalling to SafeComHolderAny/SafeComHolderPreemp.
src/coreclr/vm/interoputil.cpp Migrates various COM holders to SafeComHolderAny and updates extraction to Detach().
src/coreclr/vm/interopconverter.cpp Updates COM IP acquisition helpers to use SafeComHolderAny and Detach().
src/coreclr/vm/encee.cpp Uses SafeComHolderAny for ENC metadata holders and updates comment.
src/coreclr/vm/dispparammarshaler.cpp Converts COM holders to SafeComHolderAny and replaces SuppressRelease() with Detach().
src/coreclr/vm/commodule.cpp Migrates metadata import holder to SafeComHolderAny.
src/coreclr/vm/comconnectionpoints.cpp Migrates event interface holder to SafeComHolderAny.
src/coreclr/vm/comcallablewrapper.cpp Migrates COM holders to SafeComHolderAny and updates extraction to Detach().
src/coreclr/vm/comcache.cpp Migrates stream/error-info holders to SafeComHolderAny/SafeComHolderPreemp and updates release semantics to Free().
src/coreclr/vm/clrex.cpp Migrates error-info holder to SafeComHolderAny.
src/coreclr/vm/ceeload.cpp Migrates symbol-reader and stream holders to SafeComHolderAny and switches extraction to Detach().
src/coreclr/vm/assembly.cpp Migrates metadata dispenser/emit holders to SafeComHolderAny and adjusts void** out-param usage.
src/coreclr/utilcode/loaderheap.cpp Migrates reserved-memory holder pattern to LifetimeHolder with explicit guard + raw pointer split.
src/coreclr/utilcode/loaderheap_shared.h Defines ReservedMemoryHolder as a LifetimeHolder over ReservedMemoryTraits.
src/coreclr/utilcode/interleavedloaderheap.cpp Migrates reserved/thunk memory holders to LifetimeHolder traits and adds null guard for thunk free.
src/coreclr/utilcode/explicitcontrolloaderheap.cpp Migrates reserved-memory holder pattern to LifetimeHolder with explicit guard + raw pointer split.
src/coreclr/inc/holder.h Updates guidance comment referencing SafeComHolderAny.
src/coreclr/debug/ee/debugger.cpp Switches symbol-reader holder to SafeComHolderPreemp under an existing preemptive GC scope.

Copilot's findings

  • Files reviewed: 26/26 changed files
  • Comments generated: 1

Comment thread src/coreclr/vm/wrappers.h
@AaronRobinsonMSFT AaronRobinsonMSFT added this to the 11.0.0 milestone Jul 7, 2026
AaronRobinsonMSFT and others added 2 commits July 7, 2026 12:16
wrappers.h uses LifetimeHolder and std::is_base_of directly but relied on
transitive includes for both. Include holder.h so the header is self-contained.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Freed in cooperative GC mode, so the MODE_PREEMPTIVE trait tripped a
contract fail-fast on checked builds.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 26/26 changed files
  • Comments generated: 0 new

Comment thread src/coreclr/inc/holder.h
Comment thread src/coreclr/vm/weakreferencenative.cpp Outdated
Copilot AI review requested due to automatic review settings July 8, 2026 01:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 26/26 changed files
  • Comments generated: 0 new

Copilot AI review requested due to automatic review settings July 8, 2026 01:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 26/26 changed files
  • Comments generated: 0 new

Comment thread src/coreclr/vm/olevariant.cpp
Comment thread src/coreclr/vm/peassembly.cpp Outdated
Comment thread src/coreclr/vm/assembly.cpp Outdated
Comment thread src/coreclr/vm/ceeload.cpp Outdated
- Replaced instances of SafeComHolderAnyMode with ComHolderAnyMode across multiple files to improve clarity and consistency in COM interface management.
- Updated comments to reflect the new naming conventions for COM holder classes.
- Ensured that the new ComHolderAnyMode and ComHolderPreemp are used in contexts where preemptive mode is necessary, maintaining the intended functionality.
- Adjusted related documentation to guide developers on the appropriate usage of the new holder classes.
Copilot AI review requested due to automatic review settings July 8, 2026 03:00
@AaronRobinsonMSFT
AaronRobinsonMSFT requested a review from jkotas July 8, 2026 03:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 27/27 changed files
  • Comments generated: 1

Comment thread src/coreclr/vm/assembly.cpp Outdated
Copilot AI review requested due to automatic review settings July 8, 2026 03:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 27/27 changed files
  • Comments generated: 2

Comment thread src/coreclr/vm/ceeload.cpp
Comment thread src/coreclr/vm/peassembly.cpp
@AaronRobinsonMSFT
AaronRobinsonMSFT merged commit 3252308 into dotnet:main Jul 8, 2026
111 checks passed
@AaronRobinsonMSFT
AaronRobinsonMSFT deleted the safecomholderpreemp-lifetime branch July 8, 2026 14:44
@github-project-automation github-project-automation Bot moved this to Done in AppModel Jul 8, 2026
@dotnet-milestone-bot dotnet-milestone-bot Bot modified the milestones: 11.0.0, 11.0-preview7 Jul 10, 2026
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Continues the incremental migration of CoreCLR's legacy `Wrapper` /
`SpecializedWrapper`-based RAII holders to the trait-based
`LifetimeHolder<Traits>` pattern.

- **`ComHolderPreemp<T>` → `LifetimeHolder<ComHolderPreempTraits<T>>`.**
`Free` releases the COM interface in preemptive mode via
`SafeReleasePreemp` (NULL-safe).
- **Convert clearly-preemptive `SafeComHolder` sites to
`ComHolderPreemp`.** These call sites destruct their holder while the
thread is in preemptive mode (enclosing function is `MODE_PREEMPTIVE`,
or the holder is scoped after a `GCX_PREEMP`), so they can use the
preemptive-only release path and avoid the coop→preempt bounce in
`SafeRelease`.
- **`SafeComHolder` → `ComHolderAnyMode` (mode-agnostic).**
`ComHolderAnyModeTraits::Free()` runs under `MODE_ANY` and calls
`SafeRelease`, which transitions to preemptive internally when required.
- **utilcode loader-heap holders** (`ReservedMemoryHolder`,
`ThunkMemoryHolder`) migrated to `LifetimeHolder` traits. Sites that
previously called `SuppressRelease()` and kept using the pointer are
split into a raw `BYTE*` value plus a holder that owns the memory purely
as an error-path guard, relinquishing ownership via `Detach()` on
success. Added a NULL guard to `ReleaseAllocatedThunks` since
`LifetimeHolder` always invokes the trait's `Free()` on destruction.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.