fix(build): turn off Xcode's Thread Performance Checker in the iOS scheme - #6882
Merged
Merged
Conversation
Xcode's Run loads the Thread Performance Checker into apps it launches on iOS 18 and later. Its SQLite tracking aborts with `Assertion failed: (0), function isBulkReadStatement, file SQLiteDatabaseTracking.cpp, line 711` when a statement is finalized after its connection was closed. SQLite allows that order, and CPython produces it when it garbage-collects an unclosed connection or when a connection is closed while a cursor still has unread rows, so apps that use `sqlite3` stopped when run from Xcode. The generated scheme now sets `disablePerformanceAntipatternChecker`, the setting behind the checker's checkbox in the scheme's Diagnostics tab. Apps that are not launched by Xcode never load the checker.
ndonkoHenri
requested review from
FeodorFitsner
and
a balanced review from Copilot
September 23, 2026 16:15
Deploying flet-website-v2 with
|
| Latest commit: |
f172eef
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://445d3a51.flet-website-v2.pages.dev |
| Branch Preview URL: | https://fix-ios-thread-performance-c.flet-website-v2.pages.dev |
Contributor
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The scheme setting needs an automated regression test before approval.
Review effort: Balanced
Findings: None
What changed in this PR
Disables Xcode’s Thread Performance Checker in generated iOS schemes to prevent SQLite assertion failures during Xcode launches.
Changes:
- Adds
disablePerformanceAntipatternChecker = "YES"to the iOSLaunchAction. - Documents the fix in the changelog.
| File | Review |
|---|---|
sdk/python/templates/build/{{cookiecutter.out_dir}}/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme |
Disables the checker; needs a template-contract regression test. |
CHANGELOG.md |
Records the fix; wording could be clearer. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
FeodorFitsner
approved these changes
Sep 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5480
Problem
Apps built with
flet buildthat usesqlite3stop when run from Xcode on iOS 18 or later:The assert isn't in SQLite or Flet. It's in
libRPAC.dylib, Xcode's Thread Performance Checker, which Xcode's Run injects into the app and, for iOS 18+ destinations, configures with its launch disk-write checks on (PERFC_ENABLE_AGPC_DISKWRITES_LAUNCH_CHECKS=1). On iOS the library wraps 19sqlite3_*functions: the close wrapper stops tracking a connection before closing it, and the finalize wrapper asserts when a statement's connection isn't tracked. So anysqlite3_finalize()after a close aborts, although SQLite allows it. Evensqlite3_close()returningSQLITE_BUSY, with the connection still open, followed bysqlite3_finalize()aborts.CPython (the same code in 3.12, 3.13 and 3.14) finalizes after closing when:
with sqlite3.connect(...)is used, which commits but doesn't close;An explicit
close()finalizes statements first, which is why the snippet posted in the issue doesn't crash.Nothing outside Xcode's Run loads the checker:
flutter run/flet debugon a simulator, home-screen launches, TestFlight and the App Store are unaffected. Xcode turns these checks on only for iOS 18+ destinations, which is why downgrading the simulator runtime "fixed" it in the issue comments. With Xcode 26+,flet debug ioson a physical device launches through LLDB (Flutter'slldbDebugging, on by default) and only falls back to Xcode's Run if that fails.Changes
Runner.xcscheme: the LaunchAction setsdisablePerformanceAntipatternChecker = "YES", the setting behind the Thread Performance Checker checkbox in the scheme's Diagnostics tab. Only Xcode's Run uses it; builds and archives are unchanged. Anyone who wants the checker can turn it back on in the scheme editor.No docs change:
flet buildre-renders the template when the Flet version changes, so existing projects pick this up on upgrade.Why not the alternatives
PERFC_ENABLE_SQLITE_WRITE_STATEMENT_INSPECTION=0in the scheme's environment: also fixes it (verified) and keeps the checker's other warnings, but it's an undocumented internal switch that Apple can rename._sqlite3: the checker would no longer see the calls, but it adds app size and CVE upkeep for a debug-only problem.client/ios: doesn't embed Python, and the checker's warnings are useful to people working on the client natively, so it's unchanged.Testing
Xcode 27.0 (27A266a), iOS 18.6 simulator (iPhone 16 Pro), Python 3.14.7, an app built with
flet build ios-simulatorand started with Xcode's Run action (driven over JXA, as flutter_tools does):with sqlite3.connect()close()with unread rows¹ Launched with the environment Xcode injects (
simctl launch) rather than through Xcode itself.__assert_rtncaughtisBulkReadStatement(SQLiteDatabaseTracking.cpp, line 711), called from libRPAC'sinterposed_sqlite3_finalize, called from_sqlite3. The code from the issue runs even with the current scheme, since it closes explicitly.customLLDBInitFileandenableGPUValidationModeas strings) and anotherflet build; Xcode doesn't rewrite it.Summary by Sourcery
Disable Xcode’s Thread Performance Checker in generated iOS schemes to prevent sqlite3-related crashes during Xcode launches.
Bug Fixes:
Chores: