nvaccess / nvda

NVDA, the free and open source Screen Reader for Microsoft Windows
https://www.nvaccess.org/
Other
2.12k stars 637 forks source link

LibreOffice gets stuck when using a certain java macro while NVDA is running #14698

Closed FalkoBabbage closed 1 year ago

FalkoBabbage commented 1 year ago

Steps to reproduce:

A customer of ours has a macro to start text templates in LibreOffice. A minimal example can be run as follows:

Actual behavior:

The LibreOffice Writer appears but does not respond anymore. NVDA also does not give any information while LibreOffice is focused. Even if NVDA is closed LibreOffice still will not respond. LibreOffice can only be shut down in the task manager.

Expected behavior:

LibreOffice will open with a specified document. NVDA continues to run normally.

NVDA logs, crash dumps and other attachments:

libreOffice_debugWithoutMSAA.txt libreOffice_debugWithMSAA.txt NVDA does not seem to handle an event well.

System configuration

NVDA installed/portable/running from source:

NVDA 2022.4 installed, no addons, default configuration

NVDA version:

NVDA 2022.4

Windows version:

Edition Windows 10 Pro Version 22H2 OS build 19045.2604 Experience Windows Feature Experience Pack 120.2212.4190.0

Name and version of other software in use when reproducing the issue:

LibreOffice 7.5

Other information about your system:

Other questions

Does the issue still occur after restarting your computer?

yes

Have you tried any other versions of NVDA? If so, please report their behaviors.

No, but I am expecting the same behaviour.

If NVDA add-ons are disabled, is your problem still occurring?

No addons running

Does the issue still occur after you run the COM Registration Fixing Tool in NVDA's tools menu?

yes

Other notes

The same problem occurs in JAWS 2021. I am having trouble identifying this problem. It seems that LibreOffice is firing an event that NVDA does not handle correctly or that the event from LibreOffice is incorrect. I cannot find a way to properly debug this problem unfortunately. I would like to spend time on this but I do not have any idea on how to handle these events on this level and how to identify events that should be ignored by NVDA.

FalkoBabbage commented 1 year ago

A certain window in this setup of LibreOffice gets stuck when it gets asked if it got a UIA server provider (in UIAHandler/init.py) or when the AccessibleObjectFromEvent in ia2LiveRegions.cpp is called. I have "fixed" this by letting isBadUIAWindow return True for the appmodule and by filtering out the event hook when the process is soffice.bin.

Since the program hangs on external functions this is not something that can be fixed from NVDA's side. I have made an equivalent script in go, and there NVDA does seem to work nice with this function of LibreOffice, so I guess there is some twerk in the java code that causes this problem. NVDA shouldn't hang, but the problem is very niche and if it should be fixed my guess is that it should be fixed from the point of LibreOffice / java code.

Adriani90 commented 1 year ago

cc: @michaelweghorn

michaelweghorn commented 1 year ago

This is a deadlock in LibreOffice that occurs because the document is loaded in a non-main thread that holds to so-called SolarMutex, but then the a11y event is handled in the main thread, which tries to acquired the SolarMutex (that is held by the other thread).

This can be avoided by passing the parameter to load the document in the main thread in the XComponentLoader#loadComponentFromURL call.

No longer freezes for me with that change in place in the Java test program:

--- a/nvda-test/src/main/java/lo6test/Main.java
+++ b/nvda-test/src/main/java/lo6test/Main.java
@@ -60,8 +60,12 @@ public class Main {

         // ALERT: this is where NVDA/LibreOffice freeze
         // they do not freeze when passing "private:factory/swriter"
-        System.out.printf("load %s\n", OFFICE_DOCUMENT);
-               XComponent xComponent = xComponentLoader.loadComponentFromURL(OFFICE_DOCUMENT, "_default", 0, new PropertyValue[]{});
+        // load in main thread to prevent deadlock
+        PropertyValue prop = new PropertyValue();
+        prop.Name = "OnMainThread";
+        prop.Value = Boolean.TRUE;
+               System.out.printf("load %s\n", OFFICE_DOCUMENT);
+               XComponent xComponent = xComponentLoader.loadComponentFromURL(OFFICE_DOCUMENT, "_default", 0, new PropertyValue[]{prop});
                return xComponent;
        }