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.