[Foundation] Don't dispose tagged pointers. Fixes #21425.

TODO: better description.

Fixes https://github.com/xamarin/xamarin-macios/issues/21425.
This commit is contained in:
Rolf Bjarne Kvinge 2024-10-15 11:34:57 +02:00
Родитель 209de6f297
Коммит 6a514490e0
4 изменённых файлов: 99 добавлений и 1 удалений

Просмотреть файл

@ -573,6 +573,9 @@
<!-- Set default ValidateObjectPointers value -->
<_ValidateObjectPointers Condition="'$(_ValidateObjectPointers)' == ''">false</_ValidateObjectPointers>
<!-- Set default DisposeTaggedPointers value -->
<_DisposeTaggedPointers Condition="'$(_DisposeTaggedPointers)' == ''">true</_DisposeTaggedPointers>
<_CustomLinkerOptions>
AreAnyAssembliesTrimmed=$(_AreAnyAssembliesTrimmed)
AssemblyName=$(AssemblyName).dll
@ -687,6 +690,7 @@
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.IsManagedStaticRegistrar" Value="$(_IsManagedStaticRegistrarFeature)" Trim="true" />
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.IsNativeAOT" Value="$(_IsNativeAOTFeature)" Trim="true" />
<RuntimeHostConfigurationOption Include="ObjCRuntime.Class.ValidateObjectPointers" Value="$(_ValidateObjectPointers)" Trim="true" />
<RuntimeHostConfigurationOption Include="ObjCRuntime.NSObject.DisposeTaggedPointers" Value="$(_DisposeTaggedPointers)" Trim="true" />
<!-- Mark all assemblies to be copied if we're not linking any assemblies -->
<ResolvedFileToPublish

Просмотреть файл

@ -998,13 +998,49 @@ namespace Foundation {
handle = NativeHandle.Zero;
}
// This option is turned on by setting _DisposeTaggedPointers property to true in the project file.
static bool dispose_tagged_pointers;
static bool DisposeTaggedPointers {
get => dispose_tagged_pointers;
set => dispose_tagged_pointers = value;
}
protected virtual void Dispose (bool disposing)
{
if (disposed)
return;
disposed = true;
if (handle != NativeHandle.Zero) {
/* Tagged pointer is limited to 64bit, which is all we support anyway.
*
* The tagged pointer bit is:
*
* Arm64: most significant bit
* Simulators (both on arm64 and x64 desktops): most significant bit
* Desktop/x64 (macOS + Mac Catalyst): least significant bit
* Ref: https://github.com/apple-oss-distributions/objc4/blob/89543e2c0f67d38ca5211cea33f42c51500287d5/runtime/objc-internal.h#L603-L672
*/
#if __MACOS__ || __MACCATALYST__
ulong _OBJC_TAG_MASK;
if (Runtime.IsARM64CallingConvention) {
_OBJC_TAG_MASK = 1UL << 63;
} else {
_OBJC_TAG_MASK = 1UL;
}
#else
const ulong _OBJC_TAG_MASK = 1UL << 63;
#endif
bool isTaggedPointer;
unchecked {
var ulongHandle = (ulong) (IntPtr) handle;
isTaggedPointer = (ulongHandle & _OBJC_TAG_MASK) == _OBJC_TAG_MASK;
}
if (!DisposeTaggedPointers && isTaggedPointer) {
// don't dispose tagged pointers.
FreeData (); // still need to do this though.
} else if (handle != NativeHandle.Zero) {
if (disposing) {
ReleaseManagedRef ();
} else {

Просмотреть файл

@ -1,5 +1,9 @@
<linker>
<assembly fullname="Microsoft.macOS">
<type fullname="Foundation.NSObject">
<method signature="System.Boolean get_DisposeTaggedPointers()" body="stub" feature="Foundation.NSObject.DisposeTaggedPointers" featurevalue="false" value="false" />
<method signature="System.Boolean get_DisposeTaggedPointers()" body="stub" feature="Foundation.NSObject.DisposeTaggedPointers" featurevalue="true" value="true" />
</type>
<type fullname="ObjCRuntime.Dlfcn">
<method signature="System.Void WarnOnce()" body="stub" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false" />
</type>

Просмотреть файл

@ -0,0 +1,54 @@
using System;
using Foundation;
using NUnit.Framework;
namespace MonoTouchFixtures.ObjCRuntime {
[TestFixture]
[Preserve (AllMembers = true)]
public class TaggedPointerTest {
[Test]
public void TaggedPointersArentDisposed ()
{
var notificationData =
"""
{
action = "action";
aps =
{
category = "ee";
"content-available" = dd;
"mutable-content" = cc;
sound = bb;
"thread-id" = "aa";
};
"em-account" = "a";
"em-account-id" = "b";
"em-body" = "c";
"em-date" = "d";
"em-from" = "e";
"em-from-address" = "f";
"em-notification" = g;
"em-notification-id" = h;
"em-subject" = "i";
"gcm.message_id" = j;
"google.c.a.e" = k;
"google.c.fid" = l;
"google.c.sender.id" = m;
}
""";
var data = NSData.FromString (notificationData);
var fmt = NSPropertyListFormat.OpenStep;
var userInfo = (NSMutableDictionary) NSPropertyListSerialization.PropertyListWithData (data, NSPropertyListReadOptions.Immutable, ref fmt, out var error);
var apsKey = new NSString ("aps");
// Iteration here should not throw ObjectDisposedExceptions
foreach (var kv in userInfo) {
apsKey.Dispose ();
}
}
}
}