Skip to content

Refactor: Async getServerPPD() via authconn worker to prevent UI freezes - #482

Merged
alexpevzner merged 6 commits into
masterfrom
fix/driverless-ppd-validation-v2
Oct 20, 2026
Merged

alexpevzner merged 6 commits into
masterfrom
fix/driverless-ppd-validation-v2

Conversation

@SinghCod3r

Copy link
Copy Markdown
Collaborator

Overview

This PR introduces Prototype of a dedicated CUPS background worker integrated directly into authconn.Connection. It safely moves the blocking pycups operation getServerPPD() off the GTK main thread, resolving severe UI freezes during driverless PPD validation.

Importantly, this is achieved while completely preserving the existing authconn semantics (authentication, polkit integration, retries, server-error handling, and operation bookkeeping).

Key Changes

  • Threaded authconn Worker:
    • Implemented _worker_loop and _execute_in_worker() in authconn.py.
    • Blocking CUPS operations are routed to a dedicated background thread with its own isolated cups.Connection.
    • The GTK main thread continues pumping the GLib event loop while waiting, ensuring the UI (e.g., Cancel buttons, Spinners) remains fully responsive.
  • Wizard Lifecycle Race Fix (newprinter.py):
    • Because the UI remains responsive, users can cancel the wizard while getServerPPD() is executing in the background.
    • Added explicit getattr(self, 'device', None) is None safety checks immediately after async validation returns. If the wizard was destroyed/cancelled via on_NPCancel(), the late worker result is safely abandoned, preventing hard AttributeError: 'NoneType' object has no attribute 'driverless' crashes.
  • Deterministic Regression Testing:
    • Added test_regression_getServerPPD_cancellation_real_v2_race to test_newprinter.py.
    • This test uses deterministic threading.Event synchronization to orchestrate the exact production race: it blocks the worker, triggers a genuine on_NPCancel() callback in the GTK loop, unblocks the worker, and verifies the late result is safely discarded without exceptions.

Architecture Notes & Known Debt

  • Thread Isolation: CUPS connections are strictly owned per-thread to avoid libcups context corruption.
  • Polling Mechanism: The GTK thread currently waits for the worker by pumping a local GLib.MainLoop() and polling a shared queue using a 20ms GLib.timeout_add. While functional, a future iteration should upgrade this to a proper asynchronous eventfd or pipe() wakeup mechanism via GLib.io_add_watch.

@alexpevzner alexpevzner changed the title Refactor: Async getServerPPD() via authconn worker to prevent UI freezes (Prototype V2) Refactor: Async getServerPPD() via authconn worker to prevent UI freezes Oct 20, 2026
@alexpevzner
alexpevzner merged commit f7ebc9f into master Oct 20, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants