diff --git a/src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs b/src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs index 8ddca591075a0..315f6b90c3e0d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs @@ -110,6 +110,10 @@ public void SetTarget(T target) if ((th & ComAwareBit) != 0 || comInfo != null) { ComAwareWeakReference.SetTarget(ref _taggedHandle, target, comInfo); + + // must keep the instance alive as long as we use the handle. + GC.KeepAlive(this); + return; } #endif @@ -133,13 +137,22 @@ private T? Target if (th == 0) return default; + T? target; + #if FEATURE_COMINTEROP || FEATURE_COMWRAPPERS if ((th & ComAwareBit) != 0) - return Unsafe.As(ComAwareWeakReference.GetTarget(th)); + { + target = Unsafe.As(ComAwareWeakReference.GetTarget(th)); + + // must keep the instance alive as long as we use the handle. + GC.KeepAlive(this); + + return target; + } #endif // unsafe cast is ok as the handle cannot be destroyed and recycled while we keep the instance alive - T? target = Unsafe.As(GCHandle.InternalGet(th)); + target = Unsafe.As(GCHandle.InternalGet(th)); // must keep the instance alive as long as we use the handle. GC.KeepAlive(this); diff --git a/src/libraries/System.Private.CoreLib/src/System/WeakReference.cs b/src/libraries/System.Private.CoreLib/src/System/WeakReference.cs index 932dcb0220db7..bff571aa5166e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/WeakReference.cs +++ b/src/libraries/System.Private.CoreLib/src/System/WeakReference.cs @@ -157,13 +157,22 @@ public virtual object? Target if (th == 0) return default; + object? target; + #if FEATURE_COMINTEROP || FEATURE_COMWRAPPERS if ((th & ComAwareBit) != 0) - return ComAwareWeakReference.GetTarget(th); + { + target = ComAwareWeakReference.GetTarget(th); + + // must keep the instance alive as long as we use the handle. + GC.KeepAlive(this); + + return target; + } #endif // unsafe cast is ok as the handle cannot be destroyed and recycled while we keep the instance alive - object? target = GCHandle.InternalGet(th); + target = GCHandle.InternalGet(th); // must keep the instance alive as long as we use the handle. GC.KeepAlive(this); @@ -186,6 +195,10 @@ public virtual object? Target if ((th & ComAwareBit) != 0 || comInfo != null) { ComAwareWeakReference.SetTarget(ref _taggedHandle, value, comInfo); + + // must keep the instance alive as long as we use the handle. + GC.KeepAlive(this); + return; } #endif diff --git a/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj b/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj index a71005526deea..68390026d9e6d 100644 --- a/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj +++ b/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj @@ -4,8 +4,6 @@ true true - - true