nvda
10427e3f - Catch exceptions from AutoPropertyObject.invalidateCaches. (#15753)

Commit
2 years ago
Catch exceptions from AutoPropertyObject.invalidateCaches. (#15753) Summary of the issue: Occasionally, particularly while using consoles, I'm seeing this in my log: ERROR - unhandled exception (15:56:01.125) - MainThread (23428): Traceback (most recent call last): File "wx\core.pyc", line 3427, in <lambda> File "core.pyc", line 746, in processRequest File "core.pyc", line 769, in Notify File "baseObject.pyc", line 181, in invalidateCaches File "weakref.pyc", line 470, in keys RuntimeError: dictionary changed size during iteration After that, NVDA won't respond to commands or events. It logs input, but that's it. Eventually, I'll see a watchdog freeze error: ERROR - watchdog.waitForFreezeRecovery (15:56:16.715) - watchdog (18804): Core frozen in stack! (15.582445899999584 seconds) INFO - watchdog.waitForFreezeRecovery (15:56:16.751) - watchdog (18804): Listing stacks for Python threads: ... Python stack for thread 23428 (MainThread): File "nvda.pyw", line 399, in <module> File "core.pyc", line 813, in main File "wx\core.pyc", line 2262, in MainLoop We copy the WeakKeyDictionary's keys to avoid an issue like this. However, that isn't enough. It seems that an instance gets added to the dictionary while keys() is running. My guess is that we switched threads while keys() was running and some other thread cached a property. invalidateCaches failing for a single pump isn't really a big deal. The real nasty problem is that we don't catch the exception in the core pump, so we don't clean up correctly, which means the pump never runs again! I'm not able to reproduce this reliably. It seems to have started pretty recently. I'm wondering whether it is somehow related to the switch to Python 3.11. Description of user facing changes Fixed the freeze. Description of development approach Tracking this down is probably going to be pretty difficult. Even if/when we do, a correct solution is unclear. We could have a lock for the cache, but that could detriment performance for a cache which was implemented precisely to improve performance. For now, this change just catches the exception from invalidateCaches in the core pump and logs it. Missing one cache invalidation isn't a big deal; we'll just handle it in the next pump. It's not clean, but I think it's a pragmatic first step to deal with the clear and present danger. And we should never, ever let unhandled exceptions break us out of the core pump anyway.
Author
Parents
Loading