fix(daemon): move blocking MAP poll I/O off the GLib main loop#171
Merged
Conversation
…n-97mlk.3) A stalled OBEX transfer used to freeze the entire daemon — ANCS notification delivery, oFono call control, and all D-Bus dispatch — for up to 15s per transfer, because poll_inbox ran its folder listing, per-message body transfers, and time.sleep status polling directly on the main loop. That head-of-line blocking plausibly reads as 'ANCS regressed again' when the real culprit is a slow message fetch. - new tincand/obex_worker.py: SerialWorker, a single lazily-started worker thread that runs blocking OBEX jobs in submit order (MAP folder state requires serialization anyway) and marshals completions back to the main loop via GLib.idle_add; InlineWorker test double - MapBackend: poll_inbox split into _poll_fetch (blocking OBEX I/O, worker thread) and _process_poll_results (SQLite store + service signals, main loop); poll_inbox keeps its synchronous contract for direct callers and tests - _poll_tick now submits to the worker and returns immediately; ticks that fire while a poll is in flight are skipped; a session generation counter drops stale completions across disconnect/reconnect; dead- session recovery moved to the completion callback - dbus.mainloop.glib.threads_init() at daemon startup so the worker thread may use D-Bus connections Sends intentionally stay synchronous: their D-Bus reply semantics change with the daemon-owned send lifecycle (pending→sent→failed) planned under tincan-xbtct, and converting them now would churn the SendMessage contract twice. Co-Authored-By: Claude Fable 5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the reliability baseline (#167), bead tincan-97mlk.3.
Problem: a slow or hung OBEX transfer froze the whole daemon — ANCS delivery, call control, every D-Bus method — for up to 15s per transfer, because the MAP poll ran folder listings, per-message body transfers, and
time.sleepstatus polling directly on the GLib main loop. Head-of-line blocking that plausibly presents as "ANCS regressed again."Fix: a serialized OBEX worker thread (
tincand/obex_worker.py). MAP folder state requires serialized operations anyway, so one worker owning all blocking OBEX I/O is the natural shape:_poll_ticksubmits the I/O half and returns immediately; results marshal back to the main loop (where the SQLite store and D-Bus signal emission stay); a session-generation counter drops stale completions across reconnects; overlapping ticks are skipped while a poll is in flight.Deliberately out of scope: sends stay synchronous — their reply semantics change with the daemon-owned send lifecycle (tincan-xbtct), so converting them now would churn the
SendMessagecontract twice.Testing: full suite green (all daemon + GUI tests), plus a new
tests/tincand/test_obex_worker.pycovering worker ordering/marshalling/busy semantics and the tick/skip/stale-completion/dead-session paths. Live validation to watch for after merge: messages still arrive on poll, and the UI/calls stay responsive while a large MMS body is being fetched.🤖 Generated with Claude Code