Signal-iOS/Signal
george-signal 98acf9687a
Fix a crash in stories tableview. (#4692)
Commit 04737ff044
attempted to fix an assertion in
StoriesViewController due to UITableView
complaining about inconsistent state. The issue
continues to happen. This diff fixes it once and
for all (I hope!).

The scenario that caused a crash prior to
04737ff044 was:

  Initially:
  models = [a,b,c]

  Database changes to [a,b]

  reloadStories (loading queue)
      newModels = [a,b]
      schedule block to run on main queue

  Database changes to [x, b]

  updateStories (loading queue)
      captures self.models, value is [a,b,c] // cue ominous music
      load from database
      newModels = [x,b]
      schedule block to run on main queue; will delete c and change a to x

  reloadStories.block runs on main queue
      self.models=newModels, value is [a,b]
      tableView.reloadData()  // UITableView thinks c is deleted

  updateStories.block runs on main queue
      self.models=newModels, value is [x,b]
      tableView.beginUpdates()
      tableView.delete(index: 2)  // crashes because c was already deleted

Post-04737ff the following scenario causes a
crash:

  Initially:
  models = [a,b,c]

  Database changes to [a,b]

  updateStories (loading queue)
      load from database
      models.set([a,b])
      schedule block to run on main queue which will delete c

  iOS gets a wild hair and decides to call some
  UITableViewDataSource methods.

  tableView(_, numberOfRowsInSection:)
      return [a,b].count  // Now UIKit thinks c is gone

  updateStories.block runs on main queue
      tableView.beginUpdates()
      tableView.delete(index: 2)  // crashes because 2 is out of bounds vs number of rows

This commit fixes the problem by ensuring the
read-modify-write that happens in updateStories
never reads older data than what UITableView
has been told about and also that updates to the
model are properly synchronized with
beginUpdates()...endUpdates().

Here's how to think about it: the database goes
through a series of changes. Call them v1, v2,
..., vN.

The loading queue will see each in turn. For each,
it will enqueue a corresponding block on the main
queue to update `model` and tell UITableView about
it.

From the POV of the main queue, each update occurs
in the scope of a UITableView update.

From the POV of the loading queue, each update
reads from exactly the preceding version (from
`trueModels`) and writes to exactly the next
version of `trueModels`.

Therefore, there are no data races.
2022-08-08 10:34:39 -07:00
..
AudioFiles Don't use CallKit for video calls received while the app is active 2020-08-17 15:41:10 -07:00
Images.xcassets Allow creation of private stories 2022-07-15 15:05:03 -07:00
Lottie Adjust megaphone priority and remove old megaphones 2022-01-24 10:42:34 -08:00
NSE-Images.xcassets Cache built avatars to disk for NSE 2022-02-14 11:59:13 -08:00
Settings.bundle SignalServiceKit: no longer a separate pod 2022-08-05 16:14:15 -05:00
Sounds Autoplay subsequent audio messages 2021-04-29 18:01:21 -07:00
src Fix a crash in stories tableview. (#4692) 2022-08-08 10:34:39 -07:00
test Add remaining disappearing message time in detail view 2022-08-04 11:58:39 -05:00
translations Add camera + text controls to in-app camera 2022-08-05 08:07:44 -05:00
.swiftlint.yml
iTunesArtwork@3x.png
main.m Call UIApplicationMain() outside of autoreleasepool 2021-04-08 13:35:17 -07:00
Signal-AppStore.entitlements iOS 15 communication notification support for messages 2021-08-17 10:48:39 -10:00
Signal-Info.plist "Bump build to 5.50.0.6." (nightly-08-08-2022) 2022-08-08 11:36:03 -05:00
Signal-Prefix.pch Label the "slow write transactions" logging with the source of the transaction. 2020-06-07 10:37:55 -03:00
Signal.entitlements iOS 15 communication notification support for messages 2021-08-17 10:48:39 -10:00
SignalTSan.supp
SignalUBSan.supp