Skip to content

Commit d52235f

Browse files
vtjnashKristofferC
authored andcommitted
macOS: workaround a dyld/libunwind deadlock issue since 12.1
Apple reintroduced the old bug that we previously worked around in fad04d3 with a similar patch to this. This is needed anywhere that we may attempt to stop threads. Fixes #43578 (cherry picked from commit 2939272)
1 parent f5d02a1 commit d52235f

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

src/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ endif
119119
CLANG_LDFLAGS := $(LLVM_LDFLAGS)
120120
ifeq ($(OS), Darwin)
121121
CLANG_LDFLAGS += -Wl,-undefined,dynamic_lookup
122+
OSLIBS += $(SRCDIR)/mach_dyld_atfork.tbd
122123
endif
123124

124125
COMMON_LIBPATHS := -L$(build_libdir) -L$(build_shlibdir)

src/mach_dyld_atfork.tbd

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--- !tapi-tbd
2+
# copied from XCode's libSystem.tbd (current-version: 1311)
3+
# to provide weak-linkage info for new symbols on old systems
4+
tbd-version: 4
5+
targets: [ x86_64-macos, x86_64-maccatalyst, arm64-macos, arm64-maccatalyst,
6+
arm64e-macos, arm64e-maccatalyst ]
7+
uuids:
8+
- target: x86_64-macos
9+
value: AFE6C76A-B47A-35F5-91D0-4E9FC439E90D
10+
- target: x86_64-maccatalyst
11+
value: AFE6C76A-B47A-35F5-91D0-4E9FC439E90D
12+
- target: arm64-macos
13+
value: 2EA09BDB-811B-33AA-BB58-4B53AA2DB522
14+
- target: arm64-maccatalyst
15+
value: 2EA09BDB-811B-33AA-BB58-4B53AA2DB522
16+
- target: arm64e-macos
17+
value: 09AB3723-C26D-3762-93BA-98E9C38B89C1
18+
- target: arm64e-maccatalyst
19+
value: 09AB3723-C26D-3762-93BA-98E9C38B89C1
20+
install-name: '/usr/lib/libSystem.B.dylib'
21+
exports:
22+
- targets: [ arm64-macos, arm64e-macos, x86_64-macos, x86_64-maccatalyst,
23+
arm64-maccatalyst, arm64e-maccatalyst ]
24+
symbols: [ __dyld_atfork_parent, __dyld_atfork_prepare ]
25+
...

src/signals-mach.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ extern void *_keymgr_get_and_lock_processwide_ptr(unsigned int key);
3131
extern int _keymgr_get_and_lock_processwide_ptr_2(unsigned int key, void **result);
3232
extern int _keymgr_set_lockmode_processwide_ptr(unsigned int key, unsigned int mode);
3333

34+
// private dyld3/dyld4 stuff
35+
extern void _dyld_atfork_prepare(void) __attribute__((weak_import));
36+
extern void _dyld_atfork_parent(void) __attribute__((weak_import));
37+
//extern void _dyld_fork_child(void) __attribute__((weak_import));
38+
3439
static void attach_exception_port(thread_port_t thread, int segv_only);
3540

3641
// low 16 bits are the thread id, the next 8 bits are the original gc_state
@@ -521,6 +526,28 @@ static kern_return_t profiler_segv_handler
521526
}
522527
#endif
523528

529+
static int jl_lock_profile_mach(void)
530+
{
531+
jl_lock_profile();
532+
void *unused = NULL;
533+
int keymgr_locked = _keymgr_get_and_lock_processwide_ptr_2(KEYMGR_GCC3_DW2_OBJ_LIST, &unused) == 0;
534+
if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL)
535+
_dyld_atfork_prepare();
536+
return keymgr_locked;
537+
}
538+
539+
static void jl_unlock_profile_mach(int keymgr_locked)
540+
{
541+
if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL)
542+
_dyld_atfork_parent();
543+
if (keymgr_locked)
544+
_keymgr_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
545+
jl_unlock_profile();
546+
}
547+
548+
#define jl_lock_profile() int keymgr_locked = jl_lock_profile_mach()
549+
#define jl_unlock_profile() jl_unlock_profile_mach(keymgr_locked)
550+
524551
void *mach_profile_listener(void *arg)
525552
{
526553
(void)arg;
@@ -539,8 +566,6 @@ void *mach_profile_listener(void *arg)
539566
// sample each thread, round-robin style in reverse order
540567
// (so that thread zero gets notified last)
541568
jl_lock_profile();
542-
void *unused = NULL;
543-
int keymgr_locked = _keymgr_get_and_lock_processwide_ptr_2(KEYMGR_GCC3_DW2_OBJ_LIST, &unused) == 0;
544569
for (i = jl_n_threads; i-- > 0; ) {
545570
// if there is no space left, break early
546571
if (jl_profile_is_buffer_full()) {
@@ -593,8 +618,6 @@ void *mach_profile_listener(void *arg)
593618
// We're done! Resume the thread.
594619
jl_thread_resume(i, 0);
595620
}
596-
if (keymgr_locked)
597-
_keymgr_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST);
598621
jl_unlock_profile();
599622
if (running) {
600623
// Reset the alarm

0 commit comments

Comments
 (0)