[前][次][番号順一覧][スレッド一覧]

ruby-changes:73821

From: Yuta <ko1@a...>
Date: Sat, 1 Oct 2022 15:58:42 +0900 (JST)
Subject: [ruby-changes:73821] 7f2c548255 (ruby_3_0): Initialize Objective-C classes before fork() for macOS 13

https://git.ruby-lang.org/ruby.git/commit/?id=7f2c548255

From 7f2c548255c2e9cf5c7089823153a8a06940f174 Mon Sep 17 00:00:00 2001
From: Yuta Saito <kateinoigakukun@g...>
Date: Sat, 24 Sep 2022 03:36:04 +0900
Subject: Initialize Objective-C classes before fork() for macOS 13

Since macOS 13, CFString family API used in
`rb_str_append_normalized_ospath` may internally use Objective-C classes
(`NSTaggedPointerString` and `NSPlaceholderMutableString`) for small strings.

On the other hand, Objective-C classes should not be used for the first
time in a `fork()`'ed but not `exec()`'ed process. Violations for this rule
can result deadlock during class initialization, so Objective-C runtime
conservatively crashes on such cases by default.

Therefore, we need to use CFString API to initialize Objective-C classes
used internally *before* `fork()`.

For more details, see https://bugs.ruby-lang.org/issues/18912
---
 file.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/file.c b/file.c
index a5656861ca..dc832a8d9c 100644
--- a/file.c
+++ b/file.c
@@ -268,6 +268,46 @@ rb_str_encode_ospath(VALUE path) https://github.com/ruby/ruby/blob/trunk/file.c#L268
 
 #ifdef __APPLE__
 # define NORMALIZE_UTF8PATH 1
+
+# ifdef HAVE_WORKING_FORK
+static void
+rb_CFString_class_initialize_before_fork(void)
+{
+    /*
+     * Since macOS 13, CFString family API used in
+     * rb_str_append_normalized_ospath may internally use Objective-C classes
+     * (NSTaggedPointerString and NSPlaceholderMutableString) for small strings.
+     *
+     * On the other hand, Objective-C classes should not be used for the first
+     * time in a fork()'ed but not exec()'ed process. Violations for this rule
+     * can result deadlock during class initialization, so Objective-C runtime
+     * conservatively crashes on such cases by default.
+     *
+     * Therefore, we need to use CFString API to initialize Objective-C classes
+     * used internally *before* fork().
+     *
+     * For future changes, please note that this initialization process cannot
+     * be done in ctor because NSTaggedPointerString in CoreFoundation is enabled
+     * after CFStringInitializeTaggedStrings(), which is called during loading
+     * Objective-C runtime after ctor.
+     * For more details, see https://bugs.ruby-lang.org/issues/18912
+     */
+
+    /* Enough small but non-empty ASCII string to fit in NSTaggedPointerString. */
+    const char small_str[] = "/";
+    long len = sizeof(small_str) - 1;
+
+    const CFAllocatorRef alloc = kCFAllocatorDefault;
+    CFStringRef s = CFStringCreateWithBytesNoCopy(alloc,
+                                                  (const UInt8 *)small_str,
+                                                  len, kCFStringEncodingUTF8,
+                                                  FALSE, kCFAllocatorNull);
+    CFMutableStringRef m = CFStringCreateMutableCopy(alloc, len, s);
+    CFRelease(m);
+    CFRelease(s);
+}
+# endif
+
 static VALUE
 rb_str_append_normalized_ospath(VALUE str, const char *ptr, long len)
 {
@@ -6462,6 +6502,10 @@ const char ruby_null_device[] = https://github.com/ruby/ruby/blob/trunk/file.c#L6502
 void
 Init_File(void)
 {
+#if defined(__APPLE__) && defined(HAVE_WORKING_FORK)
+    rb_CFString_class_initialize_before_fork();
+#endif
+
     VALUE separator;
 
     rb_mFileTest = rb_define_module("FileTest");
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]