From 7243648ed7d7fefb2b2befa6dd80f5f9c46ab3d8 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Fri, 21 Aug 2026 16:06:24 -0400 Subject: [PATCH] Register the DB backup idle observer only once per connection The observer was added on every open with no matching removal, so each reopen left behind another registration that received its own idle notification. On macOS, where the periodic backup closes and reopens the connection, the registrations accumulated and multiplied the work done on each idle. Addresses #6027 --- chrome/content/zotero/xpcom/db.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js index 649c87a619..9d38793bf7 100644 --- a/chrome/content/zotero/xpcom/db.js +++ b/chrome/content/zotero/xpcom/db.js @@ -37,6 +37,7 @@ Zotero.DBConnection = function (dbNameOrPath) { } this.MAX_BOUND_PARAMETERS = 999; + this.IDLE_OBSERVER_SECONDS = 300; this.DB_CORRUPTION_STRINGS = [ "database disk image is malformed", "2152857611" @@ -1672,12 +1673,20 @@ Zotero.DBConnection.prototype._getConnectionAsync = async function () { } // Register idle observer for DB backup - Zotero.Schema.schemaUpdatePromise.then(() => { - Zotero.debug("Initializing DB backup idle observer"); - var idleService = Components.classes["@mozilla.org/widget/useridleservice;1"] - .getService(Components.interfaces.nsIUserIdleService); - idleService.addIdleObserver(this, 300); - }); + if (!this._idleObserverScheduled) { + this._idleObserverScheduled = true; + Zotero.Schema.schemaUpdatePromise.then(() => { + // The database can be closed permanently while this is pending + if (this._connection === false) { + return; + } + Zotero.debug("Initializing DB backup idle observer"); + var idleService = Components.classes["@mozilla.org/widget/useridleservice;1"] + .getService(Components.interfaces.nsIUserIdleService); + idleService.addIdleObserver(this, this.IDLE_OBSERVER_SECONDS); + this._idleObserverRegistered = true; + }); + } } // Re-load any extensions loaded via loadExtension(), which are registered per connection and