https://bugs.documentfoundation.org/show_bug.cgi?id=172229

            Bug ID: 172229
           Summary: [macOS Tahoe / Apple Silicon] Any filesystem write
                    from Python OXT extension background thread hangs
                    LibreOffice — storeToURL, .uno:Save dispatcher, and
                    AsyncCallback all affected
           Product: LibreOffice
           Version: 26.2.3.2 release
          Hardware: ARM
                OS: macOS (All)
            Status: UNCONFIRMED
          Severity: normal
          Priority: medium
         Component: Extensions
          Assignee: [email protected]
          Reporter: [email protected]

Description:
Any UNO operation that writes to the filesystem hangs LibreOffice indefinitely
(spinning beachball, requires force-quit) when called from a Python extension's
background HTTP handler thread. In-RAM operations against the same document
(property reads, cell value mutations, text insertion via insertString,
paragraph style changes, etc.) all work normally on the same thread. The
boundary is specifically filesystem I/O.
Confirmed broken — all hang LO requiring force-quit:
    1. doc.storeToURL(url, props) on a visible document with a live frame 
    2. loadComponentFromURL without Hidden=True (renderer initialization
triggers disk read of theme/profile data) 
    3. XDispatchHelper.executeDispatch(frame, ".uno:Save", "", 0, ()) —
dispatcher framework does not route around the underlying problem; same hang as
direct storeToURL 
Confirmed working — all execute cleanly from the same background thread
context:
    • loadComponentFromURL with Hidden=True (no renderer init, no disk read of
profile/theme data) 
    • All Calc cell mutations (setValue, setFormula, setString, property
assignments) 
    • All Writer in-RAM mutations (text.insertString, cursor.setPropertyValue,
text.insertControlCharacter) 
    • All property reads (getURL, isModified, getCurrentController, getText,
etc.) 
    • Style application, find/replace, page setup property mutations 
    • Document info retrieval via the desktop service 

Steps to Reproduce:
1.Create a Python OXT extension with an HTTP server running in a daemon
background thread (e.g., http.server.HTTPServer started from createInstance)
2.From the HTTP handler thread, obtain a reference to the active document via
desktop.getCurrentComponent() 
3.Make changes to the document via UNO in-RAM calls — confirm these succeed 
4.Attempt to persist those changes via any of: doc.storeToURL(), doc.store(),
or XDispatchHelper.executeDispatch(frame, ".uno:Save", "", 0, ()) 
5.Observe: LibreOffice enters the spinning beachball state indefinitely and
must be force-quit

Actual Results:
Observe: LibreOffice enters the spinning beachball state indefinitely and must
be force-quit. LibreOffice hangs indefinitely (spinning beachball). The hang is
unrecoverable and requires force-quit. No crash report, no recovery file, no
autosave residue — the document state at the moment of the call is lost.)

Expected Results:
File Saved successfully A save call (whether direct storeToURL, doc.store(), or
.uno:Save dispatch) issued from a Python extension's background thread should
complete successfully, with LO either handling the filesystem write on its own
main thread (as the documentation implies dispatcher calls do) or returning a
clear error indicating thread-context restrictions.
Equivalent code patterns worked correctly on prior macOS + LibreOffice versions
(pre-Tahoe, pre-26.2). The regression appears to be introduced by the combined
macOS Tahoe + LO 26.2 update.)


Reproducible: Always


User Profile Reset: Yes

Additional Info:
    • com.sun.star.awt.AsyncCallback with a Python object implementing
XCallback — addCallback() registers cleanly (requires bundling offapi.rdb in
the OXT, otherwise rejected with value does not implement
com.sun.star.awt.XCallback), drainer_status endpoint reports
mode=async_callback, but notifyAsyncOperation() never fires. Queue accumulates
items and times out after 30s. 
    • toolkit.queryInterface(XReschedule).reschedule() from the background
thread to pump the main event loop — call returns without error but does not
cause notifyAsyncOperation() to fire or unblock pending main-thread work 
    • com.sun.star.util.theTimer — returns None; service does not exist on
macOS in LO 26.2 
    • theIdleManager for XIdleListener registration — does not exist in LO 26.2 
    • Routing the dispatch call through XDispatchHelper instead of storeToURL
directly — same hang outcome 


Additional context — note on offapi.rdb:
For other developers hitting the AsyncCallback registration error, the
XCallback type definition is not in the URE-only types.rdb (~56KB) that ships
in a default OXT skeleton. The full offapi.rdb (~668KB) from
/Applications/LibreOffice.app/Contents/Resources/types/offapi.rdb must be
bundled in the OXT. After this fix, addCallback() accepts Python XCallback
implementations cleanly. The remaining problem — notifyAsyncOperation() never
firing — is independent of the type registration issue.

Hypothesis:
The combination of macOS Tahoe's tightened main-thread UI enforcement and LO
26.2's Skia/Metal renderer changes on Apple Silicon appears to have closed off
the cross-thread dispatch mechanisms (AsyncCallback, XDispatchHelper,
XReschedule) that previously allowed Python extension background threads to
safely trigger main-thread filesystem operations. The dispatch calls themselves
succeed (register, return, no exception) but the work never runs on the main
thread.

Impact:
Python OXT extensions that perform document modifications and saves on behalf
of external clients (e.g., MCP servers, AI assistants, automation tools) cannot
persist their changes on macOS Tahoe + LO 26.2. The only workaround is to
direct end users to save manually via Cmd+S after each batch of changes, which
defeats the automation use case.

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to