mattermost-mobile-upstream/ios/Gekidou/Tests/GekidouTests
Pavel Zeman 41239064bb
fix: prevent SQLite crash from concurrent database access in iOS (Sentry YND+YNE, 36K users) (#9610)
* fix: prevent SQLite crash from concurrent database access in iOS

Replace all unsafe db.prepare() iteration patterns with safe
prepareRowIterator + failableNext() in the Gekidou Storage layer.

SQLite.swift 0.15.4 uses `try!` in FailableIterator.next() (Statement.swift:218),
which means any SQLite error during row iteration crashes the app instantly.
This is triggered when the main app and NotificationService extension access
the shared database concurrently, causing SQLITE_BUSY ("database is locked").

Two-part fix:
1. Add busyTimeout (5s) to all SQLite connections via new openConnection()
   helper, so transient locks are retried instead of failing immediately.
2. Replace db.prepare(query) iteration with prepareRowIterator() +
   failableNext(), which returns throwable errors instead of crashing
   via try!. Also replace db.prepare(string).scalar() with db.scalar().

Files changed:
- Database.swift: Add openConnection() helper, fix 4 methods
- Database+Users.swift: Fix queryUsers(byIds:), queryUsers(byUsernames:),
  getUserLastPictureAt (YND/YNE crash sites)
- Database+Thread.swift: Fix handleThreads team ID iteration
- Database+Team.swift: Fix queryAllMyTeamIds
- Database+Channels.swift: Fix serverHasChannels scalar query
- Database+Mentions.swift: Fix getChannelMentions, getThreadMentions
- Database+System.swift: Fix getDeviceToken connection creation

Sentry: https://mattermost-mr.sentry.io/issues/7117724547/ (YND, 20K users)
Sentry: https://mattermost-mr.sentry.io/issues/7118237218/ (YNE, 15K users)

Co-authored-by: Claude <claude@anthropic.com>

* fix: address CodeRabbit review on SQLite safe iteration

- Replace Array(iterator).map with explicit failableNext() loops in
  Database.swift and Database+Users.swift. Array(iterator) still goes
  through SQLite.swift's non-throwing next() which uses try! internally,
  defeating the purpose of the safe iteration fix.
- Remove unsafe sqlite3_close_v2() test that violated Connection
  ownership (double-free risk). Replace with proper lock contention
  test using DELETE journal mode + EXCLUSIVE lock.
- Fix concurrent access test: WAL mode allows readers during writes
  without exercising busyTimeout. Switched to DELETE journal mode
  with EXCLUSIVE lock + async release to actually test the retry path.

Co-authored-by: Claude <claude@anthropic.com>

---------

Co-authored-by: Claude <claude@anthropic.com>
2026-03-20 16:17:34 -04:00
..
DatabaseSafeIterationTests.swift fix: prevent SQLite crash from concurrent database access in iOS (Sentry YND+YNE, 36K users) (#9610) 2026-03-20 16:17:34 -04:00
GekidouTests.swift iOS - Fetch and store data on push notification receipt (#5645) 2021-08-31 15:43:57 -07:00