Fix deadlock between nvWave stop and feed#11886
Merged
feerrenrut merged 2 commits intobetafrom Dec 8, 2020
Merged
Conversation
feerrenrut
commented
Dec 4, 2020
| winmm.waveOutPrepareHeader(self._waveout, LPWAVEHDR(whdr), sizeof(WAVEHDR)) | ||
| winmm.waveOutWrite(self._waveout, LPWAVEHDR(whdr), sizeof(WAVEHDR)) | ||
| self.sync() # sync must still be called even if stopping, so that waveOutUnprepareHeader can be called | ||
| self._prev_whdr = whdr |
Contributor
Author
There was a problem hiding this comment.
I think this is a bug, in the case that nvWave is stopping, we shouldn't save this unprepared header.
Member
There was a problem hiding this comment.
But what then would unprepare that header? saving it off means that feed / sync will unprepare it next time (I think) not saving it, and setting _prev_whdr to None, you'd have to specifically call waveOutUnprepare for hdr I think?
The base branch was changed.
Contributor
Author
|
This should be in 2020.4. @michaelDCurran are you still happy with this? |
Member
|
@feerrenrut I'm happy for this to be in 2020.4, yes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Link to issue number:
fixes #11591
Summary of the issue:
On at least one user's system, a deadlock seems to occur while using NVDA with the oneCore synth. This results in a freeze and a stack dump by the watchdog.
Stacks to note, from log:
Because I can't reproduce this, I'm having to reason about how the code got into this state. What seems to have happened is that
feedandstophave been called at the same time from the synth thread and the main thread respectively. These have both progressed to sub-routines,syncand_idleUnbufferedrespectively._idleUnbufferedis blocked waiting to acquire theself._lock, andsynchas acquired theself._lockmutex and is blocked bywaitForSingleObject.feedhas no locks until it calls into_feedUnbuffered, howeverstopdoes acquire locks that_feedUnbufferedneeds, then releases them and then calls to_idleUnbufferedwhich has contention with_feedUnbufferedagain. It seems to me that the only way to get into this situation is ifstopacquires the locks it needs first. It callswaveOutReset, then when it releases the locks and before they are acquired by_idleUnbufferedthey are instead acquired by_feedUnbuffered. This results inwaveOutWritebeing called before progressing tosyncand waiting onwaitForSingleObjectIt's still not entirely clear to me why this set of events causes a deadlock. My best guess is that on this particular system, the
whdr(Wave Out Header) which includesdwFlagsthat should have theWHDR_DONEbit set when the associated buffer has finished being played is not getting updated due to the call to reset. Thus the synth thread gets stuck in a loop callingwaitForSingleObjectand checking_prev_whdr.Alternatively, it may be that the stack is not representative of the freeze?
Description of how this pull request fixes the issue:
Because I'm not 100% sure of the cause of the problem, I have covered a few potentials:
waitForSingleObjectnow has a timeout, it then will check ifnvWavehas been stopped before waiting again.winmisn't explicit about whether this is handled.Relevant Info from Docs:
When opening
winmdevice, the event signal args:waveOutReset:
The locking logic for
nvWaveis complicated, however given plans to re writenvWavewith modern Windows API's I think we should hold off on doing more than we need to resolve this specific issueTesting performed:
Ran locally with oneCore
Known issues with pull request:
None
Change log entry:
None