NVDA freezes iTunes in web views #6502

Closed
jcsteh opened this Issue Oct 25, 2016 · 1 comment

Comments

Projects
None yet
2 participants
@jcsteh
Contributor

jcsteh commented Oct 25, 2016

OS: Windows 10 64 bit
iTunes version: 12.5.1.21 64 bit

STR:

  1. Search for a song in Apple Music. The iTunes Store will probably do it too.
  2. Press f6 to move into the web view.
  3. Keep pressing (or even hold) downArrow.
    • Expected: NVDA should navigate through the document.
    • Actual: Eventually, iTunes freezes, taking NVDA with it.
@jcsteh

This comment has been minimized.

Show comment
Hide comment
@jcsteh

jcsteh Oct 25, 2016

Contributor

Debugging this reveals a deadlock in our vbuf backend:

  1. getNativeHandleForNode gets called in an RPC thread. It acquires the backend lock and sends a window message to the main thread.
  2. The main thread runs the update timer proc. It calls update, which eventually tries to acquire the lock.
  3. Unfortunately, it hasn't yet processed the message sent by getNativeHandleForNode yet, but getNativeHandleForNode is still holding the lock waiting for a response to that message. The main thread can't process the message because it's waiting on the lock. Deadlock!

Relevant stack from main thread:

 # Child-SP          RetAddr           Call Site
00 00000065`715fee88 00007ffe`58d7acb7 ntdll!NtWaitForAlertByThreadId+0x14
01 00000065`715fee90 00007ffe`58d7abce ntdll!RtlpWaitOnAddressWithTimeout+0x43
02 00000065`715feec0 00007ffe`58d7aa63 ntdll!RtlpWaitOnAddress+0xb2
03 00000065`715fef30 00007ffe`58d7760c ntdll!RtlpWaitOnCriticalSection+0xdb
04 00000065`715ff000 00007ffe`58d77360 ntdll!RtlpEnterCriticalSectionContended+0x160
05 00000065`715ff030 00007ffe`2a53acdb ntdll!RtlEnterCriticalSection+0x40
06 00000065`715ff060 00007ffe`2a5482df VBufBackend_webKit!LockableObject::acquire(void)+0x1b [c:\projects\nvda\build\x86_64\common\lock.h @ 44]
07 00000065`715ff090 00007ffe`2a547ea1 VBufBackend_webKit!VBufBackend_t::update(void)+0x1df [c:\projects\nvda\build\x86_64\vbufbase\backend.cpp @ 206]
08 00000065`715ff1c0 00007ffe`577105c1 VBufBackend_webKit!VBufBackend_t::renderThread_timerProc(struct HWND__ * hwnd = 0x00000000`00000000, unsigned int msg = 0x113, unsigned int64 timerID = 0x3c30, unsigned long time = 0x13989d0d)+0xd1 [c:\projects\nvda\build\x86_64\vbufbase\backend.cpp @ 118]
09 00000065`715ff210 00007ffe`57711ade USER32!UserCallWinProc+0x231
...

Relevant stack from RPC thread:

00 00000065`751fe718 00007ffe`57711631 win32u!NtUserMessageCall+0x14
01 00000065`751fe720 00007ffe`577114d2 USER32!SendMessageWorker+0xf1
02 00000065`751fe7b0 00007ffe`2a54ee41 USER32!SendMessageW+0x112
03 00000065`751fe810 00007ffe`40799d14 VBufBackend_webKit!WebKitVBufBackend_t::getNodeForNativeHandle(int nativeHandle = 0n2356)+0x51 [c:\projects\nvda\build\x86_64\vbufbackends\webkit\webkit.cpp @ 314]
04 00000065`751fe870 00007ffe`57f5a3b3 nvdaHelperRemote!VBufRemote_getNodeForNativeHandle(void * buffer = 0x0000023c`e43dd560, int nativeHandle = 0n2356, unsigned int64 * node = 0x00000065`751feec0)+0x44 [c:\projects\nvda\build\x86_64\remote\vbufremote.cpp @ 177]
05 00000065`751fe8b0 00007ffe`57f402f7 RPCRT4!Invoke+0x73
Contributor

jcsteh commented Oct 25, 2016

Debugging this reveals a deadlock in our vbuf backend:

  1. getNativeHandleForNode gets called in an RPC thread. It acquires the backend lock and sends a window message to the main thread.
  2. The main thread runs the update timer proc. It calls update, which eventually tries to acquire the lock.
  3. Unfortunately, it hasn't yet processed the message sent by getNativeHandleForNode yet, but getNativeHandleForNode is still holding the lock waiting for a response to that message. The main thread can't process the message because it's waiting on the lock. Deadlock!

Relevant stack from main thread:

 # Child-SP          RetAddr           Call Site
00 00000065`715fee88 00007ffe`58d7acb7 ntdll!NtWaitForAlertByThreadId+0x14
01 00000065`715fee90 00007ffe`58d7abce ntdll!RtlpWaitOnAddressWithTimeout+0x43
02 00000065`715feec0 00007ffe`58d7aa63 ntdll!RtlpWaitOnAddress+0xb2
03 00000065`715fef30 00007ffe`58d7760c ntdll!RtlpWaitOnCriticalSection+0xdb
04 00000065`715ff000 00007ffe`58d77360 ntdll!RtlpEnterCriticalSectionContended+0x160
05 00000065`715ff030 00007ffe`2a53acdb ntdll!RtlEnterCriticalSection+0x40
06 00000065`715ff060 00007ffe`2a5482df VBufBackend_webKit!LockableObject::acquire(void)+0x1b [c:\projects\nvda\build\x86_64\common\lock.h @ 44]
07 00000065`715ff090 00007ffe`2a547ea1 VBufBackend_webKit!VBufBackend_t::update(void)+0x1df [c:\projects\nvda\build\x86_64\vbufbase\backend.cpp @ 206]
08 00000065`715ff1c0 00007ffe`577105c1 VBufBackend_webKit!VBufBackend_t::renderThread_timerProc(struct HWND__ * hwnd = 0x00000000`00000000, unsigned int msg = 0x113, unsigned int64 timerID = 0x3c30, unsigned long time = 0x13989d0d)+0xd1 [c:\projects\nvda\build\x86_64\vbufbase\backend.cpp @ 118]
09 00000065`715ff210 00007ffe`57711ade USER32!UserCallWinProc+0x231
...

Relevant stack from RPC thread:

00 00000065`751fe718 00007ffe`57711631 win32u!NtUserMessageCall+0x14
01 00000065`751fe720 00007ffe`577114d2 USER32!SendMessageWorker+0xf1
02 00000065`751fe7b0 00007ffe`2a54ee41 USER32!SendMessageW+0x112
03 00000065`751fe810 00007ffe`40799d14 VBufBackend_webKit!WebKitVBufBackend_t::getNodeForNativeHandle(int nativeHandle = 0n2356)+0x51 [c:\projects\nvda\build\x86_64\vbufbackends\webkit\webkit.cpp @ 314]
04 00000065`751fe870 00007ffe`57f5a3b3 nvdaHelperRemote!VBufRemote_getNodeForNativeHandle(void * buffer = 0x0000023c`e43dd560, int nativeHandle = 0n2356, unsigned int64 * node = 0x00000065`751feec0)+0x44 [c:\projects\nvda\build\x86_64\remote\vbufremote.cpp @ 177]
05 00000065`751fe8b0 00007ffe`57f402f7 RPCRT4!Invoke+0x73

@jcsteh jcsteh self-assigned this Oct 25, 2016

jcsteh added a commit that referenced this issue Oct 26, 2016

@jcsteh jcsteh closed this in #6503 Nov 14, 2016

@nvaccessAuto nvaccessAuto added this to the 2016.4 milestone Nov 14, 2016

jcsteh added a commit that referenced this issue Nov 14, 2016

iTunes no longer intermittently freezes forever when using browse mod…
…e for the iTunes Store, Apple Music, etc. (#6502)

This was due to a deadlock between an RPC thread and the main thread when NVDA called getNativeHandleForNode and the main thread was attempting to render at the same time.
WebKit now supports IAccessible2 uniqueID. We now use this instead of our getNativeHandleForNode hack, as it's a much cleaner, safer and more reliable way to marshal objects between processes. This does mean we no longer support iTunes versions from a few years ago, but I doubt Apple does either and iTunes is free anyway.
getNativeHandleForNode and getNodeForNativeHandle have been removed from vbuf backend. They suffer from this deadlock, they're extremely ugly, and they were only introduced to support WebKit before it got IA2 anyway.
PR #6503.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment