Improve task cancellation management in SubscriptionManager

The widespread usage of the SubscriptionManager caused new crashes to
occur when swapping apps.

This was caused due to an access to Ndb memory after Ndb has been closed
from the app background signal.

The issue was fixed with improved task management logic and ensuring all
subscription tasks are finished before closing Ndb.

Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
Daniel D’Aquino
2025-08-27 12:10:36 -07:00
parent 76b6d5c545
commit a5aff15491
6 changed files with 72 additions and 10 deletions

View File

@@ -698,9 +698,13 @@ class Ndb {
// Fetch initial results
guard let txn = NdbTxn(ndb: self) else { throw .cannotOpenTransaction }
do { try Task.checkCancellation() } catch { throw .cancelled }
// Use our safe wrapper instead of direct C function call
let noteIds = try query(with: txn, filters: filters, maxResults: maxSimultaneousResults)
do { try Task.checkCancellation() } catch { throw .cancelled }
// Create a subscription for new events
let newEventsStream = ndbSubscribe(filters: filters)
@@ -717,6 +721,7 @@ class Ndb {
// Create a task to forward events from the subscription stream
let forwardingTask = Task {
for await item in newEventsStream {
try Task.checkCancellation()
continuation.yield(item)
}
continuation.finish()
@@ -876,6 +881,7 @@ extension Ndb {
case cannotConvertFilter(any Error)
case initialQueryFailed
case timeout
case cancelled
}
/// An error that may happen when looking something up