Skip to content

Commit

Permalink
Fix a rare deadlock in watchdog termination, inability to force quit/…
Browse files Browse the repository at this point in the history
…restart NVDA if it freezes during exit and another rare watchdog edge case.

See the code comments and/or the ticket for full details.
Fixes #5189.
  • Loading branch information
jcsteh committed Jul 15, 2015
1 parent f52bd5a commit 8e912ec
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 2 deletions.
4 changes: 3 additions & 1 deletion source/core.py
Expand Up @@ -371,7 +371,6 @@ def Notify(self):
app.MainLoop()

log.info("Exiting")
messageWindow.destroy()
if updateCheck:
_terminate(updateCheck)

Expand Down Expand Up @@ -413,6 +412,9 @@ def Notify(self):
nvwave.playWaveFile("waves\\exit.wav",async=False)
except:
pass
# #5189: Destroy the message window as late as possible
# so new instances of NVDA can find this one even if it freezes during exit.
messageWindow.destroy()
log.debug("core done")

def _terminate(module, name=None):
Expand Down
8 changes: 7 additions & 1 deletion source/watchdog.py
Expand Up @@ -64,10 +64,16 @@ def alive():
def asleep():
"""Inform the watchdog that the core is going to sleep.
"""
# #5189: Reset in case the core was treated as dead.
alive()
# CancelWaitableTimer does not reset the signaled state; if it was signaled, it remains signaled.
# However, alive() calls SetWaitableTimer, which resets the timer to unsignaled.
windll.kernel32.CancelWaitableTimer(_coreDeadTimer)

def _isAlive():
return winKernel.waitForSingleObject(_coreDeadTimer, 0) != 0
# #5189: If the watchdog has been terminated, treat the core as being alive.
# This will stop recovery if it has started and allow the watcher to terminate.
return not isRunning or winKernel.waitForSingleObject(_coreDeadTimer, 0) != 0

def _watcher():
global isAttemptingRecovery
Expand Down

0 comments on commit 8e912ec

Please sign in to comment.