Skip to content

Fix suspend of CLR initialization thread when started from dispatch queue on apple - #135276

Merged
BrzVlad merged 3 commits into
mainfrom
fix-mac-thread-suspend
Oct 16, 2026
Merged

BrzVlad merged 3 commits into
mainfrom
fix-mac-thread-suspend

Conversation

@BrzVlad

@BrzVlad BrzVlad commented Oct 6, 2026

Copy link
Copy Markdown
Member

Suspending for GC requires first sending a signal to a thread (so that we can check the thread context and determine what action needs to be taken for suspending this thread at a GC safe location). On apple platforms, threads dispatched via dispatch_async have this signal masked (INJECT_ACTIVATION_SIGNAL). When a foreign thread is attached to the runtime, it goes through AllocatePalThread path, which already does the necessary unmasking of the signal. When CoreCLR was started from a thread dispatched via dispatch_async, which is the case in the mobile tests runner, we weren't unmasking the signal for this initial thread. This resulted in a thread potentially never stopping from GC and the app hanging.

macios never initializes CoreCLR from such a worker thread, so this fix is targeted only to our testing.

Fixes #134770

…patch queue on apple

Suspending for GC requires first sending a signal to a thread (so that we can check the thread context and determine what action needs to be taken for suspending this thread at a GC safe location). On apple platforms, threads dispatched via `dispatch_async` have this signal masked (`INJECT_ACTIVATION_SIGNAL`). When a foreign thread is attached to the runtime, it goes through `AllocatePalThread` path, which already does the necessary unmasking of the signal. When CoreCLR was started from a thread dispatched via `dispatch_async`, which is the case in the mobile tests runner, we weren't unmasking the signal for this initial thread. This resulted in a thread potentially never stopping from GC and the app hanging.

macios never initializes CoreCLR from such a worker thread, so this fix is targeted only to our testing.

Reenable test
@BrzVlad BrzVlad changed the title Fix thread suspend of clr initialization thread when started from dispatch queue on apple Fix suspend of CLR initialization thread when started from dispatch queue on apple Oct 6, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Comment thread src/coreclr/pal/src/exception/signal.cpp
Comment thread src/coreclr/pal/src/exception/signal.cpp
Comment thread src/coreclr/pal/src/exception/signal.cpp Outdated
@BrzVlad

BrzVlad commented Oct 16, 2026

Copy link
Copy Markdown
Member Author

/ba-g failures unrelated

@BrzVlad
BrzVlad merged commit 201e33f into main Oct 16, 2026
106 of 108 checks passed
@BrzVlad
BrzVlad deleted the fix-mac-thread-suspend branch October 16, 2026 05:29
XLord-Heliukum added a commit to Open-code-Studio/CodeNet that referenced this pull request Oct 17, 2026
现象:macOS 27 上 CodeNet 运行时在 GC 标记阶段 SIGSEGV/SIGBUS,
栈为 mark_object_simple1 <- mark_object_simple <- GcStackCrawlCallBack
<- EnumerateLiveSlots <- Promote <- gc_heap::mark_phase,
且把栈上的 ASCII 数据当成对象指针解引用。WKS 与 SVR 都能复现。

根因:GC 要挂起线程得先给线程发注入激活信号(INJECT_ACTIVATION_SIGNAL)。
由 launchd / libdispatch 起出来的线程进入进程时该信号是屏蔽的,
GC 于是永远等不到线程停到 safepoint,继续扫描一个还在跑的栈,
把任意栈内容当成对象引用 —— 这就是 mark 阶段的崩溃。

上游同类问题的修法见 dotnet/runtime#135276(BrzVlad):
把 PAL 内部的 UnmaskActivationSignal 导出成 PAL_UnmaskActivationSignal,
并在 CLR 侧线程挂接时调用。本仓库按同样思路移植,
区别是挂在 SetThread 的通用挂接路径上(而不是只处理初始线程),
因为这里的成灾面是所有继承了启动者信号掩码的线程。

改动:
- pal.h 导出 PAL_UnmaskActivationSignal
- signal.cpp 增加 extern "C" 导出包装(CodeNet 强制 HAVE_MACH_EXCEPTIONS=0,
  该文件信号路径必被编译)
- threads.cpp 的 SetThread 在 InitRuntimeThreadLocals 之后解除屏蔽

附带:SDK 组装脚本关掉 SDK CLI 自身的并发 GC(治标,压住构建期的偶发崩溃),
产物校验从「与骨架原件哈希不同」改成「与运行时源文件哈希一致」,
并新增 scripts/codenet-sdk/verify-stability.sh 做本机回归。
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Apple][CoreCLR] GC suspension never completes in b425314: runtime can't suspend a tight R2R loop

3 participants