def sync(self): """Synchronise with playback. This method blocks until the previously fed chunk of audio has finished playing. It is called automatically by L{feed}, so usually need not be called directly by the user. Note: it must be possible to call stop concurrently with sync, sync should be considered to be blocking the synth driver thread most of the time (ie sync waiting for the last pushed block of audio to complete, via the 'winKernal.waitForSingleObject' mechanism) """ with self._lock: if not self._prev_whdr: return assert self._waveout, "waveOut None before wait" while (not (self._prev_whdr.dwFlags & WHDR_DONE) # In case some sound driver can not keep track of the whdr from previous buffers, ensure that # 'waitForSingleObject' can not block for long, and exit this loop if stopping. and self._prevOnDone is not self.STOPPING): winKernel.waitForSingleObject(self._waveout_event, self._waveout_event_wait_ms) with self._waveout_lock: assert self._waveout, "waveOut None after wait" with self._global_waveout_lock: winmm.waveOutUnprepareHeader(self._waveout, LPWAVEHDR(self._prev_whdr), sizeof(WAVEHDR)) self._prev_whdr = None if self._prevOnDone not in (None, self.STOPPING): try: self._prevOnDone() except: log.exception("Error calling onDone") self._prevOnDone = None
def sync(self): """Synchronise with playback. This method blocks until the previously fed chunk of audio has finished playing. It is called automatically by L{feed}, so usually need not be called directly by the user. """ with self._lock: if not self._prev_whdr: return assert self._waveout, "waveOut None before wait" while not (self._prev_whdr.dwFlags & WHDR_DONE): winKernel.waitForSingleObject(self._waveout_event, winKernel.INFINITE) with self._waveout_lock: assert self._waveout, "waveOut None after wait" with self._global_waveout_lock: winmm.waveOutUnprepareHeader(self._waveout, LPWAVEHDR(self._prev_whdr), sizeof(WAVEHDR)) self._prev_whdr = None if self._prevOnDone is not None and self._prevOnDone is not self.STOPPING: try: self._prevOnDone() except: log.exception("Error calling onDone") self._prevOnDone = None
def terminateRunningNVDA(window): processID, threadID = winUser.getWindowThreadProcessID(window) winUser.PostMessage(window, winUser.WM_QUIT, 0, 0) h = winKernel.openProcess(winKernel.SYNCHRONIZE, False, processID) if not h: # The process is already dead. return try: res = winKernel.waitForSingleObject(h, 4000) if res == 0: # The process terminated within the timeout period. return finally: winKernel.closeHandle(h) # The process is refusing to exit gracefully, so kill it forcefully. h = winKernel.openProcess( winKernel.PROCESS_TERMINATE | winKernel.SYNCHRONIZE, False, processID) if not h: raise OSError("Could not open process for termination") try: winKernel.TerminateProcess(h, 1) winKernel.waitForSingleObject(h, 2000) finally: winKernel.closeHandle(h)
def sync(self): """Synchronise with playback. This method blocks until the previously fed chunk of audio has finished playing. It is called automatically by L{feed}, so usually need not be called directly by the user. """ with self._lock: if not self._prev_whdr: return assert self._waveout, "waveOut None before wait" while not (self._prev_whdr.dwFlags & WHDR_DONE): winKernel.waitForSingleObject(self._waveout_event, winKernel.INFINITE) with self._waveout_lock: assert self._waveout, "waveOut None after wait" with self._global_waveout_lock: winmm.waveOutUnprepareHeader(self._waveout, LPWAVEHDR(self._prev_whdr), sizeof(WAVEHDR)) self._prev_whdr = None
def _watcher(): global isAttemptingRecovery while True: # Wait for the core to die. winKernel.waitForSingleObject(_coreDeadTimer, winKernel.INFINITE) if not isRunning: return # The core hasn't reported alive for MIN_CORE_ALIVE_TIMEOUT. waited = MIN_CORE_ALIVE_TIMEOUT while not _isAlive() and not _shouldRecoverAfterMinTimeout(): # The core is still dead and fast recovery doesn't apply. # Wait up to NORMAL_ALIVE_TIMEOUT. time.sleep(MIN_CORE_ALIVE_TIMEOUT) waited += MIN_CORE_ALIVE_TIMEOUT if waited >= NORMAL_CORE_ALIVE_TIMEOUT: break if _isAlive(): continue if log.isEnabledFor(log.DEBUGWARNING): stacks = getFormattedStacksForAllThreads() log.debugWarning( f"Trying to recover from freeze. Listing stacks for Python threads:\n{stacks}" ) lastTime = time.time() isAttemptingRecovery = True # Cancel calls until the core is alive. # This event will be reset by alive(). windll.kernel32.SetEvent(_cancelCallEvent) # Some calls have to be killed individually. while True: curTime = time.time() if curTime - lastTime > FROZEN_WARNING_TIMEOUT: lastTime = curTime # Core is completely frozen. # Collect formatted stacks for all Python threads. log.error("Core frozen in stack!") stacks = getFormattedStacksForAllThreads() log.info(f"Listing stacks for Python threads:\n{stacks}") _recoverAttempt() time.sleep(RECOVER_ATTEMPT_INTERVAL) if _isAlive(): break isAttemptingRecovery = False
def _watcher(): global isAttemptingRecovery while True: # Wait for the core to die. winKernel.waitForSingleObject(_coreDeadTimer, winKernel.INFINITE) if not isRunning: return # The core hasn't reported alive for MIN_CORE_ALIVE_TIMEOUT. waited = MIN_CORE_ALIVE_TIMEOUT while not _isAlive() and not _shouldRecoverAfterMinTimeout(): # The core is still dead and fast recovery doesn't apply. # Wait up to NORMAL_ALIVE_TIMEOUT. time.sleep(MIN_CORE_ALIVE_TIMEOUT) waited += MIN_CORE_ALIVE_TIMEOUT if waited >= NORMAL_CORE_ALIVE_TIMEOUT: break if _isAlive(): continue if log.isEnabledFor(log.DEBUGWARNING): log.debugWarning( "Trying to recover from freeze, core stack:\n%s" % "".join( traceback.format_stack( sys._current_frames()[core.mainThreadId]))) lastTime = time.time() isAttemptingRecovery = True # Cancel calls until the core is alive. # This event will be reset by alive(). windll.kernel32.SetEvent(_cancelCallEvent) # Some calls have to be killed individually. while True: curTime = time.time() if curTime - lastTime > FROZEN_WARNING_TIMEOUT: lastTime = curTime log.warning("Core frozen in stack:\n%s" % "".join( traceback.format_stack( sys._current_frames()[core.mainThreadId]))) _recoverAttempt() time.sleep(RECOVER_ATTEMPT_INTERVAL) if _isAlive(): break isAttemptingRecovery = False
def _watcher(): global isAttemptingRecovery while True: # Wait for the core to die. winKernel.waitForSingleObject(_coreDeadTimer, winKernel.INFINITE) if not isRunning: return # The core hasn't reported alive for MIN_CORE_ALIVE_TIMEOUT. waited = MIN_CORE_ALIVE_TIMEOUT while not _isAlive() and not _shouldRecoverAfterMinTimeout(): # The core is still dead and fast recovery doesn't apply. # Wait up to NORMAL_ALIVE_TIMEOUT. time.sleep(MIN_CORE_ALIVE_TIMEOUT) waited += MIN_CORE_ALIVE_TIMEOUT if waited >= NORMAL_CORE_ALIVE_TIMEOUT: break if _isAlive(): continue if log.isEnabledFor(log.DEBUGWARNING): log.debugWarning("Trying to recover from freeze, core stack:\n%s"% "".join(traceback.format_stack(sys._current_frames()[core.mainThreadId]))) lastTime=time.time() isAttemptingRecovery = True # Cancel calls until the core is alive. # This event will be reset by alive(). windll.kernel32.SetEvent(_cancelCallEvent) # Some calls have to be killed individually. while True: curTime=time.time() if curTime-lastTime>FROZEN_WARNING_TIMEOUT: lastTime=curTime log.warning("Core frozen in stack:\n%s"% "".join(traceback.format_stack(sys._current_frames()[core.mainThreadId]))) _recoverAttempt() time.sleep(RECOVER_ATTEMPT_INTERVAL) if _isAlive(): break isAttemptingRecovery = False
def _get_isAlive(self): return bool(winKernel.waitForSingleObject(self.processHandle, 0))
def _isAlive(): # #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 _get_isAlive(self): return bool(winKernel.waitForSingleObject(self.processHandle,0))
def terminate(self): # Closing the write end of the pipe will cause EOF for the waiting loader process, which will then exit gracefully. winKernel.closeHandle(self._pipeWrite) # Wait until it's dead. winKernel.waitForSingleObject(self._process, winKernel.INFINITE) winKernel.closeHandle(self._process)
def _isAlive(): return winKernel.waitForSingleObject(_coreDeadTimer, 0) != 0