fix(sync): bail out of deferred sync tasks when the document is gone
Every push and pull runs deferred — updateProgress and getProgress hand
their work to UIManager:scheduleIn(0.5), and API replies are consumed in
UIManager:nextTick closures — so by the time the task runs, the ReaderUI
may have released its document (close/teardown race) or a slow async
load may not have attached it yet (the CRE full-render window: "cached
rendering is invalid" leaves the reader document-less for seconds on
big EPUBs). The task then dereferenced self.ui.document unguarded and
the unhandled error inside a UIManager task killed the whole app:
main.lua:846: attempt to index field 'document' (a nil value)
...in function 'collectBookData'
...in function '_doUpdateProgress'
...in function 'action' (uimanager _checkTasks)
Observed as a hard crash on the auto-push (pages_before_update = 2)
right after opening an EPUB that needed a full re-render.
getBookhoardUUID and getContextText already nil-guarded their document
access; the task entry points never did. Guard them:
- _doUpdateProgress: bail before collectBookData — the single choke
point for every push source (periodic, close, suspend, menu, the
legacy bootstrap push), so one guard covers the whole class
- _doGetProgress: bail at entry, and re-validate first thing inside the
nextTick closure (its body and applyServerAnnotations touch
document.info long after the request was issued)
- getFileSHA256: return nil instead of indexing doc_settings/document
(all callers already handle nil)
No sync-payload or endpoint changes; server behavior untouched.
This commit is contained in:
@@ -737,6 +737,9 @@ function Bookhoard:getLastProgress()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Bookhoard:getFileSHA256()
|
function Bookhoard:getFileSHA256()
|
||||||
|
-- Reached from deferred flows too (e.g. _linkBookThenPull after a
|
||||||
|
-- network-connected event); callers already handle nil.
|
||||||
|
if not (self.ui and self.ui.doc_settings and self.ui.document) then return nil end
|
||||||
local cached = self.ui.doc_settings:readSetting("bookhoard_sha256")
|
local cached = self.ui.doc_settings:readSetting("bookhoard_sha256")
|
||||||
if cached then return cached end
|
if cached then return cached end
|
||||||
|
|
||||||
@@ -1208,6 +1211,12 @@ function Bookhoard:updateProgress(ensure_networking, interactive)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Bookhoard:_doUpdateProgress(interactive)
|
function Bookhoard:_doUpdateProgress(interactive)
|
||||||
|
-- Every push runs deferred (scheduleIn(0.5) in updateProgress), so it
|
||||||
|
-- can fire after the ReaderUI released its document (close/teardown
|
||||||
|
-- race, e.g. "attempt to index field 'document'" killing the app) or
|
||||||
|
-- before a slow async load attached it (the CRE full-render window).
|
||||||
|
-- Bail silently; the next real page turn re-pushes.
|
||||||
|
if not (self.ui and self.ui.document) then return end
|
||||||
local book_data = self:collectBookData()
|
local book_data = self:collectBookData()
|
||||||
if not book_data then return end
|
if not book_data then return end
|
||||||
|
|
||||||
@@ -1441,6 +1450,9 @@ function Bookhoard:_bootstrapUUIDThenPull(interactive)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Bookhoard:_doGetProgress(interactive)
|
function Bookhoard:_doGetProgress(interactive)
|
||||||
|
-- Pulls are deferred too (see _doUpdateProgress): the document can be
|
||||||
|
-- gone — or not yet attached — by the time the timer fires.
|
||||||
|
if not (self.ui and self.ui.document) then return end
|
||||||
local book_uuid = self:getBookhoardUUID()
|
local book_uuid = self:getBookhoardUUID()
|
||||||
if not book_uuid then return end
|
if not book_uuid then return end
|
||||||
|
|
||||||
@@ -1448,6 +1460,9 @@ function Bookhoard:_doGetProgress(interactive)
|
|||||||
local ok, result = api:getMetadata(book_uuid)
|
local ok, result = api:getMetadata(book_uuid)
|
||||||
|
|
||||||
UIManager:nextTick(function()
|
UIManager:nextTick(function()
|
||||||
|
-- The HTTP reply landed after the defer; re-validate before the
|
||||||
|
-- document-dependent body below (applyServerAnnotations, sync).
|
||||||
|
if not (self.ui and self.ui.document) then return end
|
||||||
if not ok or not result then
|
if not ok or not result then
|
||||||
if interactive then
|
if interactive then
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
|
|||||||
Reference in New Issue
Block a user