prs on Nostr: fix crash related to preloading events (#1115) This PR fixes the top crash in build ...
fix crash related to preloading events (#1115)
This PR fixes the top crash in build 1.4.3(24):
<img width="376" alt="damus_—_Profiles_swift" src="
https://github.com/damus-io/damus/assets/445882/1cf51c52-920d-43a7-a832-0776790557d8">
The crash is caused by a data contention for the `profiles` dictionary in the `Profiles` class. Many views and view models access this dictionary from the main thread by calling `Profiles.lookup(id:)`. `Profiles.add(id:profile:)` is currently called only from the main thread. However, the stack trace in the crash report indicates that it happens when `Profiles.lookup(id:)` is called from a non-main thread during event preloading. When a profile is added on the main thread and a profile lookup occurs on a non-main thread at the same time, we have a data contention and the app crashes.
To resolve this, I added a concurrent `DispatchQueue` to synchronize access to the `profiles` dictionary. Concurrent reads can happen safely from both main and non-main threads, but writes will happen asynchronously and use the `barrier` flag to enforce exclusive access.
An alternative fix would be to make the `Profiles` class an `actor` instead of a `class`, which automatically synchronizes access to all of its members. I chose not to pursue this solution because it would also make `Profiles.lookup(id:)` `async`, which would change all the call sites.
profiles-crash, 1 commits
https://github.com/damus-io/damus/pull/1115Published at
2023-05-10 04:50:03Event JSON
{
"id": "7dbc3ea4dcf135287afc69affa35bec09a78d5ff0586587cc9526390b10218fc",
"pubkey": "edf16b1dd61eab353a83af470cc13557029bff6827b4cb9b7fc9bdb632a2b8e6",
"created_at": 1683694203,
"kind": 1,
"tags": [
[
"p",
"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"
],
[
"t",
"damuspr"
]
],
"content": "fix crash related to preloading events (#1115)\n\nThis PR fixes the top crash in build 1.4.3(24):\r\n\r\n\u003cimg width=\"376\" alt=\"damus_—_Profiles_swift\" src=\"https://github.com/damus-io/damus/assets/445882/1cf51c52-920d-43a7-a832-0776790557d8\"\u003e \r\n\r\nThe crash is caused by a data contention for the `profiles` dictionary in the `Profiles` class. Many views and view models access this dictionary from the main thread by calling `Profiles.lookup(id:)`. `Profiles.add(id:profile:)` is currently called only from the main thread. However, the stack trace in the crash report indicates that it happens when `Profiles.lookup(id:)` is called from a non-main thread during event preloading. When a profile is added on the main thread and a profile lookup occurs on a non-main thread at the same time, we have a data contention and the app crashes.\r\n\r\nTo resolve this, I added a concurrent `DispatchQueue` to synchronize access to the `profiles` dictionary. Concurrent reads can happen safely from both main and non-main threads, but writes will happen asynchronously and use the `barrier` flag to enforce exclusive access.\r\n\r\nAn alternative fix would be to make the `Profiles` class an `actor` instead of a `class`, which automatically synchronizes access to all of its members. I chose not to pursue this solution because it would also make `Profiles.lookup(id:)` `async`, which would change all the call sites.\n\nprofiles-crash, 1 commits\n\nhttps://github.com/damus-io/damus/pull/1115",
"sig": "13a3aead5d94811bcc07b8f3d38dcf412b9a4f807823d1679f8546e930a787f75959a7a89db398450e7629ffeef47db1ea85bb3f3d370aeae8c0aa1c92aab1e3"
}