Prevent new NostrDB streaming tasks from opening when NostrDB has begun to close

We have mechanisms in place to close NostrDB streams when the database needs to
close; however, there is a short time window where those streams are
closing down but the database still has its "open" property set to `true`,
which means that new NostrDB streams may open. If that happens, those
new streams will still be active when NostrDB gets closed down,
potentially causing memory crashes.

This was found by inspecting several crash logs and noticing that:
- most of the `ndb.close` calls are coming from the general
  backgrounding task (not the last resort backgrounding task),
  where all old tasks are guaranteed to have closed (we wait for all of
  them to close before proceeding to closing NostrDB).
- the stack traces of the crashed threads show that, in most cases, the
  stream crashes while they are in the query stage (which means that
  those must have been very recently opened).

The issue was mitigated by signalling that NostrDB has closed (without
actually closing it) before cancelling any streaming tasks and officially
closing NostrDB. This way, new NostrDB streaming tasks will notice that
the database is closed and will wait for it to reopen.

No changelog entry is needed as this issue was introduced after our last public
release.

Changelog-None
Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
This commit is contained in:
Daniel D’Aquino
2025-11-03 15:47:45 -08:00
parent 2f7a40bd50
commit b562b930cc
3 changed files with 19 additions and 8 deletions

View File

@@ -207,6 +207,12 @@ class Ndb {
self.callbackHandler = Ndb.CallbackHandler()
}
/// Mark NostrDB as "closed" without actually closing it.
/// Useful when shutting down tasks that use NostrDB while avoiding new tasks from using it.
func markClosed() {
self.closed = true
}
func close() {
guard !self.is_closed else { return }
self.closed = true