笑死,不久之前我们才聊过 Flutter 3.41.7 在 iOS 上做的那个大修复,可算是把 iOS 26.4 下 JIT Debug 的崩溃问题搞定了。那个问题的根源在于一个上游 bug(llvm/llvm-project#190956),在异步模式(async mode)下,LLDB 会随机在重新装载(rearm)脚本化断点时失败。
换句话说,第一次断点能正常触发,Python 脚本也能顺利把内存 Page 标记为可执行。可一旦后续断点撞上了这个 bug,就不会再触发了:
这时候就会导致 Dart VM 新编译的代码 Page 没有被标记为可执行,当 DartWorker 线程尝试执行这些未标记的代码时就会报错 EXC_BAD_ACCESS (code=50)。
Flutter 官方随后通过一轮曲折的 review 和一套“严谨”的审核流程修复了这个问题:

然而,两周不到,3.41.8 就发布了,主要目的就是修复 3.41.7 带来的新 Bug。这个新问题的核心逻辑是:
JIT 断点(LLDB breakpoint)机制本来只在 debug 模式 下,通过 Dart 侧设置断点(NOTIFY_DEBUGGER_ABOUT_RX_PAGES)来触发。但 Flutter 3.41.7 的修复,却导致 profile 模式也开始执行这套 LLDB 断点等待逻辑。而 profile 模式根本不会触发这个断点,结果就是进程永久挂起。

问题发生时,日志里能清晰看到它在死等那个永远不会到来的断点事件:
[2026-04-16 02:32:28.125425] [STDOUT] stdout: [ +4 ms] executing: lldb
[2026-04-16 02:32:29.063991] [STDOUT] stdout: [ +938 ms] [lldb]: (lldb) device select 00008140-00160D5034F0801C
[2026-04-16 02:32:29.693547] [STDOUT] stdout: [ +629 ms] [lldb]: (lldb) breakpoint set --func-regex '^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$'
[2026-04-16 02:32:29.694147] [STDOUT] stdout: [ ] [lldb]: Breakpoint 1: no locations (pending).
[2026-04-16 02:32:29.694241] [STDOUT] stdout: [ ] [lldb]: Breakpoint set in dummy target, will get copied into future targets.
[2026-04-16 02:32:29.694726] [STDOUT] stdout: [ ] [lldb]: (lldb) breakpoint command add --script-type python 1
[2026-04-16 02:32:29.732521] [STDOUT] stdout: [ +37 ms] [lldb]: (lldb) script lldb.debugger.SetAsync(False)
[2026-04-16 02:32:29.733830] [STDOUT] stdout: [ +1 ms] [lldb]: (lldb) device process attach --pid 734
[2026-04-16 02:32:30.279842] [STDOUT] stdout: [ +545 ms] [lldb]: Process 734 stopped
[2026-04-16 02:32:30.279859] [STDOUT] stdout: [ ] [lldb]: * thread #1, stop reason = signal SIGSTOP
[2026-04-16 02:32:30.279885] [STDOUT] stdout: [ ] [lldb]: frame #0: 0x0000000100dd2330 dyld`_dyld_start
[2026-04-16 02:32:30.279888] [STDOUT] stdout: [ ] [lldb]: dyld`_dyld_start:
[2026-04-16 02:32:30.279890] [STDOUT] stdout: [ ] [lldb]: -> 0x100dd2330 <+0>: mov x0, sp
[2026-04-16 02:32:30.279891] [STDOUT] stdout: [ ] [lldb]: 0x100dd2334 <+4>: and sp, x0, #0xfffffffffffffff0
[2026-04-16 02:32:30.279893] [STDOUT] stdout: [ ] [lldb]: 0x100dd2338 <+8>: mov x29, #0x0 ; =0
[2026-04-16 02:32:30.279950] [STDOUT] stdout: [ ] [lldb]: 0x100dd233c <+12>: mov x30, #0x0 ; =0
[2026-04-16 02:32:30.279956] [STDOUT] stdout: [ ] [lldb]: Target 0: (Runner) stopped.
[2026-04-16 02:32:30.280354] [STDOUT] stdout: [ ] [lldb]: (lldb) process continue
[2026-04-16 02:32:33.246480] [STDOUT] stdout: [+2965 ms] 2026-04-16 02:46:20.742446-0700 Runner[734:169244] [UIFocus] FlutterView implements focusItemsInRect: - caching for linear focus movement is limited as long as this view is on screen.
[2026-04-16 02:32:33.386577] [STDOUT] stdout: [ +139 ms] 2026-04-16 02:46:20.884205-0700 Runner[734:169244] fopen failed for data file: errno = 2 (No such file or directory)
[2026-04-16 02:32:33.386883] [STDOUT] stdout: [ ] 2026-04-16 02:46:20.884367-0700 Runner[734:169244] Errors found! Invalidating cache...
[2026-04-16 02:32:33.428215] [STDOUT] stdout: [ +41 ms] 2026-04-16 02:46:20.925344-0700 Runner[734:169244] fopen failed for data file: errno = 2 (No such file or directory)
[2026-04-16 02:32:33.428323] [STDOUT] stdout: [ ] 2026-04-16 02:46:20.925451-0700 Runner[734:169244] Errors found! Invalidating cache...
[2026-04-16 02:32:33.440401] [STDOUT] stdout: [ +12 ms] 2026-04-16 02:46:20.938115-0700 Runner[734:169244] Warning: Unable to create restoration in progress marker file
[2026-04-16 02:32:33.498277] [STDOUT] stdout: [ +57 ms] 2026-04-16 02:46:20.995636-0700 Runner[734:169312] [General] Failed to send CA Event for app launch measurements for ca_event_type: 1 event_name: com.apple.app_launch_measurement.ExtendedLaunchMetrics
[2026-04-16 02:33:28.131754] [STDOUT] stderr: [+54631 ms] LLDB is taking longer than expected to start debugging the app. LLDB debugging can be disabled for the project by adding the following in the project's pubspec.yaml:
[2026-04-16 02:33:28.131839] [STDOUT] stderr: flutter:
[2026-04-16 02:33:28.131857] [STDOUT] stderr: config:
[2026-04-16 02:33:28.131909] [STDOUT] stderr: enable-lldb-debugging: false
[2026-04-16 02:33:28.131959] [STDOUT] stderr: Or disable LLDB debugging globally with the following command:
[2026-04-16 02:33:28.131970] [STDOUT] stderr: "flutter config --no-enable-lldb-debugging"
没错,3.41.8 针对的正是 3.41.7 引入的副作用,修复的作者也是同一个人。因为 3.41.7 在修 Xcode 26.4 竞态 bug 的时候,一不留神让 profile 模式也踩进了那条只有 debug 模式才有出口的死胡同。
修复的思路倒简单,就是传入一个 mode 判断,仅在 BuildMode.debug 下执行那段逻辑。可问题根本不在于修复有多简单,而是如此明显的场景,在之前那么多轮 merge 和 review 中竟无一人察觉。还能说什么呢?只能说大家都是草台班子。


另外,之前我们聊过的那个已经修复的 #175099 Webview 点击问题,起因源自苹果 WebKit 的 Bug。后来 Flutter 官方在提供修复的同时,也跟苹果那边跟进了这个问题。如今,该问题在 iOS 系统层面已经得到了解决,iOS 26.4 上默认就不会再碰到这个场景,所以从 26.4 开始,就不再需要启用之前的临时修复方案了。

说真的,这倒也不是问题本身有多低级,完全是“人有失手,马有失蹄”。哪怕换成 AI,恐怕也没法做到滴水不漏吧。在像 Flutter 这样复杂的跨平台框架里打补丁,本身就有点像“打地鼠”,按下葫芦浮起瓢,没什么稀奇的。
|