[iOS] Generate unique class name for MonoDeadLetter (#89956)
authorSteve Pfister <steveisok@users.noreply.github.com>
Tue, 8 Aug 2023 16:29:57 +0000 (09:29 -0700)
committerGitHub <noreply@github.com>
Tue, 8 Aug 2023 16:29:57 +0000 (12:29 -0400)
In library mode, it is possible to have multiple shared libraries (runtimes) loaded in the same process. On iOS, we have a small bit of objc to make sure we know when threads die so we can properly detach the runtime. Unfortunately, the class name we use is not unique and results in a crash when calling into a 2nd library.

This change makes the class name partially unique to avoid such a circumstance.

src/mono/mono/utils/mono-threads-mach-helper.c
src/native/libs/System.Native/pal_autoreleasepool.m

index 64b49ce..82f56b6 100644 (file)
@@ -122,8 +122,13 @@ mono_threads_init_dead_letter (void)
        setObjectForKey = sel_registerName ("setObject:forKey:");
        objectForKey = sel_registerName ("objectForKey:");
 
-       // define the dead letter class
-       mono_dead_letter_class = objc_allocateClassPair (nsobject, "MonoDeadLetter", 0);
+       char *class_name = g_strdup_printf ("MonoDeadLetter%p", &"MonoDeadLetter");
+
+       // Define the dead letter class
+       // The class name needs to be unique in the event different runtimes are loaded into the same process.
+       mono_dead_letter_class = objc_allocateClassPair (nsobject, class_name, 0);
+       g_free (class_name);
+
        class_addMethod (mono_dead_letter_class, dealloc, (IMP)mono_dead_letter_dealloc, "v@:");
        objc_registerClassPair (mono_dead_letter_class);
 
index e5ebd4d..191d145 100644 (file)
@@ -3,17 +3,7 @@
 
 #include "pal_autoreleasepool.h"
 #include <Foundation/Foundation.h>
-
-@interface PlaceholderObject : NSObject
-- (void)noop:(id)_;
-@end
-
-@implementation PlaceholderObject : NSObject
-- (void)noop:(id)_
-{
-    [self release];
-}
-@end
+#include <objc/runtime.h>
 
 void EnsureNSThreadIsMultiThreaded(void)
 {
@@ -22,12 +12,13 @@ void EnsureNSThreadIsMultiThreaded(void)
         // Start another no-op thread with the NSThread APIs to get NSThread into multithreaded mode.
         // The NSAutoReleasePool APIs can't be used on secondary threads until NSThread is in multithreaded mode.
         // See https://developer.apple.com/documentation/foundation/nsautoreleasepool for more information.
-        PlaceholderObject* placeholderObject = [[PlaceholderObject alloc] init];
-
+        //
         // We need to use detachNewThreadSelector to put NSThread into multithreaded mode.
         // We can't use detachNewThreadWithBlock since it doesn't change NSThread into multithreaded mode for some reason.
         // See https://developer.apple.com/documentation/foundation/nswillbecomemultithreadednotification for more information.
-        [NSThread detachNewThreadSelector:@selector(noop:) toTarget:placeholderObject withObject:nil];
+        id placeholderObject = [[NSMutableString alloc] init];         
+        [NSThread detachNewThreadSelector:@selector(appendString:) toTarget:placeholderObject withObject:@""];
+        [placeholderObject release];
     }
     assert([NSThread isMultiThreaded]);
 }