ruby-changes:73733
From: Yuta <ko1@a...>
Date: Mon, 26 Sep 2022 12:03:55 +0900 (JST)
Subject: [ruby-changes:73733] e3cc1a6cae (master): Initialize Objective-C classes before fork() for macOS 13
https://git.ruby-lang.org/ruby.git/commit/?id=e3cc1a6cae From e3cc1a6cae0e6c88c04cd54c3afa3c022bb6772c 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 cf67dd2aaf..709c33cca7 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) { @@ -7317,6 +7357,10 @@ const char ruby_null_device[] = https://github.com/ruby/ruby/blob/trunk/file.c#L7357 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/