|
|
Chromium Code Reviews|
Created:
3 years, 11 months ago by Raymond Toy Modified:
3 years, 11 months ago Reviewers:
hongchan CC:
chromium-reviews, blink-reviews, haraken Target Ref:
refs/pending/heads/master Project:
chromium Visibility:
Public. |
DescriptionDon't run removeFinishedSourceNodes with the context lock.
releaseFinishedSourceNodes is run from handlePostRenderTask on the
audio thread which has the context lock. releaseFinishedSourceNodes
can call removeFinishedSourceNodes which runs on the main thread which
will also get the context lock. Depending on how fast things are,
this second attempt to get the lock may happen while
handlePostRenderTask still has the lock, causing a cycle.
Therefore, move the call to removeFinishedSourceNodes outside the
lock. This is ok, since removeFinishedSourceNodes doesn't do anything
without acquiring the context lock.
BUG=681316
TEST=test case from the bug passes on a tsan build
Review-Url: https://codereview.chromium.org/2638413004
Cr-Commit-Position: refs/heads/master@{#445467}
Committed: https://chromium.googlesource.com/chromium/src/+/b82438a6b9cf9324f9d2b3780ea270b7bff62a93
Patch Set 1 #
Total comments: 2
Patch Set 2 : Add removeFinishedSourceNodesOnMainThread #
Total comments: 6
Messages
Total messages: 25 (8 generated)
The CQ bit was checked by rtoy@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
rtoy@chromium.org changed reviewers: + hongchan@chromium.org
PTAL at this preliminary patch. I think we may want to add another function named, say, requestRemovalOfFinishedSourceNodesOnMainThread (is that too long) to do the actual postTask and everything. Then we can easily add a check that we're not running with the context lock.
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
https://codereview.chromium.org/2638413004/diff/1/third_party/WebKit/Source/m... File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (left): https://codereview.chromium.org/2638413004/diff/1/third_party/WebKit/Source/m... third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:671: m_finishedSourceHandlers.clear(); We don't have this line in the patchset anymore. Is that okay?
https://codereview.chromium.org/2638413004/diff/1/third_party/WebKit/Source/m... File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (left): https://codereview.chromium.org/2638413004/diff/1/third_party/WebKit/Source/m... third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:671: m_finishedSourceHandlers.clear(); On 2017/01/19 12:47:43, hongchan wrote: > We don't have this line in the patchset anymore. Is that okay? Fixed.
https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: removeFinishedSourceNodes(didRemove); What's the difference between doing the above and this? if (didRemove) removeFinishedSourceNodes(); Furthermore, I am not sure how this change helps in fixing the problem.
https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: removeFinishedSourceNodes(didRemove); On 2017/01/20 23:27:05, hongchan wrote: > What's the difference between doing the above and this? > > if (didRemove) > removeFinishedSourceNodes(); > > Furthermore, I am not sure how this change helps in fixing the problem. Mostly less duplication in the two places that call this. By moving the remove outside the tryLock, we're not inside the graph lock when removeFinishedSourceNodesOnMainThread is run which tries to grab the lock on the main thread. I think before removeFinishedSourceNodes could run on the main thread while the tryLock was still active (holding on to the graph lock). So two different threads were contending for the same lock, but the calls are in a cycle.
https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: removeFinishedSourceNodes(didRemove); On 2017/01/21 00:12:15, Raymond Toy wrote: > On 2017/01/20 23:27:05, hongchan wrote: > > What's the difference between doing the above and this? > > > > if (didRemove) > > removeFinishedSourceNodes(); > > > > Furthermore, I am not sure how this change helps in fixing the problem. > > Mostly less duplication in the two places that call this. > > By moving the remove outside the tryLock, we're not inside the graph lock when > removeFinishedSourceNodesOnMainThread is run which tries to grab the lock on the > main thread. I think before removeFinishedSourceNodes could run on the main > thread while the tryLock was still active (holding on to the graph lock). So > two different threads were contending for the same lock, but the calls are in a > cycle. What I meant by the comment above is: why do we have to pass |didRemove| to the function? What's the scope of tryLock() here? Is it inside of the if statement? Or up to the end of handlePostRenderTasks()?
https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: removeFinishedSourceNodes(didRemove); On 2017/01/23 17:38:41, hongchan wrote: > On 2017/01/21 00:12:15, Raymond Toy wrote: > > On 2017/01/20 23:27:05, hongchan wrote: > > > What's the difference between doing the above and this? > > > > > > if (didRemove) > > > removeFinishedSourceNodes(); > > > > > > Furthermore, I am not sure how this change helps in fixing the problem. > > > > Mostly less duplication in the two places that call this. > > > > By moving the remove outside the tryLock, we're not inside the graph lock when > > removeFinishedSourceNodesOnMainThread is run which tries to grab the lock on > the > > main thread. I think before removeFinishedSourceNodes could run on the main > > thread while the tryLock was still active (holding on to the graph lock). So > > two different threads were contending for the same lock, but the calls are in > a > > cycle. > > What I meant by the comment above is: why do we have to pass |didRemove| to the > function? Just to make the logic of what to do with didRemove the same so the caller doesn't need to do the check. I'm fine having the check in the caller or the callee. > > What's the scope of tryLock() here? Is it inside of the if statement? Or up to > the end of handlePostRenderTasks()? Since there's an unlock() at line 762, the lock ends at the end of the if (tryLock()) block.
On 2017/01/23 17:45:01, Raymond Toy wrote: > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): > > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: > removeFinishedSourceNodes(didRemove); > On 2017/01/23 17:38:41, hongchan wrote: > > On 2017/01/21 00:12:15, Raymond Toy wrote: > > > On 2017/01/20 23:27:05, hongchan wrote: > > > > What's the difference between doing the above and this? > > > > > > > > if (didRemove) > > > > removeFinishedSourceNodes(); > > > > > > > > Furthermore, I am not sure how this change helps in fixing the problem. > > > > > > Mostly less duplication in the two places that call this. > > > > > > By moving the remove outside the tryLock, we're not inside the graph lock > when > > > removeFinishedSourceNodesOnMainThread is run which tries to grab the lock on > > the > > > main thread. I think before removeFinishedSourceNodes could run on the main > > > thread while the tryLock was still active (holding on to the graph lock). > So > > > two different threads were contending for the same lock, but the calls are > in > > a > > > cycle. > > > > What I meant by the comment above is: why do we have to pass |didRemove| to > the > > function? > > Just to make the logic of what to do with didRemove the same so the caller > doesn't need to do the check. I'm fine having the check in the caller or the > callee. Then returning to the square one: why do we need another function call only for postTask()? > > > > What's the scope of tryLock() here? Is it inside of the if statement? Or up to > > the end of handlePostRenderTasks()? > > Since there's an unlock() at line 762, the lock ends at the end of the if > (tryLock()) block. Yes, that's my understanding and I wasn't sure why calling another function fixes the issue of postTask().
On 2017/01/23 17:47:52, hongchan wrote: > On 2017/01/23 17:45:01, Raymond Toy wrote: > > > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > > File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): > > > > > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > > third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: > > removeFinishedSourceNodes(didRemove); > > On 2017/01/23 17:38:41, hongchan wrote: > > > On 2017/01/21 00:12:15, Raymond Toy wrote: > > > > On 2017/01/20 23:27:05, hongchan wrote: > > > > > What's the difference between doing the above and this? > > > > > > > > > > if (didRemove) > > > > > removeFinishedSourceNodes(); > > > > > > > > > > Furthermore, I am not sure how this change helps in fixing the problem. > > > > > > > > Mostly less duplication in the two places that call this. > > > > > > > > By moving the remove outside the tryLock, we're not inside the graph lock > > when > > > > removeFinishedSourceNodesOnMainThread is run which tries to grab the lock > on > > > the > > > > main thread. I think before removeFinishedSourceNodes could run on the > main > > > > thread while the tryLock was still active (holding on to the graph lock). > > So > > > > two different threads were contending for the same lock, but the calls are > > in > > > a > > > > cycle. > > > > > > What I meant by the comment above is: why do we have to pass |didRemove| to > > the > > > function? > > > > Just to make the logic of what to do with didRemove the same so the caller > > doesn't need to do the check. I'm fine having the check in the caller or the > > callee. > > Then returning to the square one: why do we need another function call only for > postTask()? To make things common truly common. Otherwise we duplicate the code in two places, begging the question if they are truly duplicates or not. > > > > > > > > What's the scope of tryLock() here? Is it inside of the if statement? Or up > to > > > the end of handlePostRenderTasks()? > > > > Since there's an unlock() at line 762, the lock ends at the end of the if > > (tryLock()) block. > > Yes, that's my understanding and I wasn't sure why calling another function > fixes the issue of postTask(). Because if we don't, the postTask is called inside the tryLock. If things are fast and the other function calls are slow, the postTask could run while the lock is still held by the audio thread. Then the main thread will try to grab the lock that is held by the audio thread. This could be a potential deadlock. (Although, I'm not sure that can really happen since the audio thread will eventually release the lock that it is holding.)
https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: removeFinishedSourceNodes(didRemove); On 2017/01/23 17:45:01, Raymond Toy wrote: > On 2017/01/23 17:38:41, hongchan wrote: > > On 2017/01/21 00:12:15, Raymond Toy wrote: > > > On 2017/01/20 23:27:05, hongchan wrote: > > > > What's the difference between doing the above and this? > > > > > > > > if (didRemove) > > > > removeFinishedSourceNodes(); > > > > > > > > Furthermore, I am not sure how this change helps in fixing the problem. > > > > > > Mostly less duplication in the two places that call this. > > > > > > By moving the remove outside the tryLock, we're not inside the graph lock > when > > > removeFinishedSourceNodesOnMainThread is run which tries to grab the lock on > > the > > > main thread. I think before removeFinishedSourceNodes could run on the main > > > thread while the tryLock was still active (holding on to the graph lock). > So > > > two different threads were contending for the same lock, but the calls are > in > > a > > > cycle. > > > > What I meant by the comment above is: why do we have to pass |didRemove| to > the > > function? > > Just to make the logic of what to do with didRemove the same so the caller > doesn't need to do the check. I'm fine having the check in the caller or the > callee. > > > > > What's the scope of tryLock() here? Is it inside of the if statement? Or up to > > the end of handlePostRenderTasks()? > > Since there's an unlock() at line 762, the lock ends at the end of the if > (tryLock()) block. > > Okay, probably this will be the last question; can we move source nodes handling logic to DFH? All other post-render tasks are handled by DFH, not the context.
https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: removeFinishedSourceNodes(didRemove); On 2017/01/23 18:08:06, hongchan wrote: > On 2017/01/23 17:45:01, Raymond Toy wrote: > > On 2017/01/23 17:38:41, hongchan wrote: > > > On 2017/01/21 00:12:15, Raymond Toy wrote: > > > > On 2017/01/20 23:27:05, hongchan wrote: > > > > > What's the difference between doing the above and this? > > > > > > > > > > if (didRemove) > > > > > removeFinishedSourceNodes(); > > > > > > > > > > Furthermore, I am not sure how this change helps in fixing the problem. > > > > > > > > Mostly less duplication in the two places that call this. > > > > > > > > By moving the remove outside the tryLock, we're not inside the graph lock > > when > > > > removeFinishedSourceNodesOnMainThread is run which tries to grab the lock > on > > > the > > > > main thread. I think before removeFinishedSourceNodes could run on the > main > > > > thread while the tryLock was still active (holding on to the graph lock). > > So > > > > two different threads were contending for the same lock, but the calls are > > in > > > a > > > > cycle. > > > > > > What I meant by the comment above is: why do we have to pass |didRemove| to > > the > > > function? > > > > Just to make the logic of what to do with didRemove the same so the caller > > doesn't need to do the check. I'm fine having the check in the caller or the > > callee. > > > > > > > > What's the scope of tryLock() here? Is it inside of the if statement? Or up > to > > > the end of handlePostRenderTasks()? > > > > Since there's an unlock() at line 762, the lock ends at the end of the if > > (tryLock()) block. > > > > > > Okay, probably this will be the last question; can we move source nodes handling > logic to DFH? All other post-render tasks are handled by DFH, not the context. Let me try. You mean DeferredTaskHandler? (Not sure what DFH is). But I don't quite follow the DFH comment since releaseFinishedSourceNodes is in BaseAudioContext, DeferredTaskHandler.
On 2017/01/23 18:11:21, Raymond Toy wrote: > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): > > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: > removeFinishedSourceNodes(didRemove); > On 2017/01/23 18:08:06, hongchan wrote: > > On 2017/01/23 17:45:01, Raymond Toy wrote: > > > On 2017/01/23 17:38:41, hongchan wrote: > > > > On 2017/01/21 00:12:15, Raymond Toy wrote: > > > > > On 2017/01/20 23:27:05, hongchan wrote: > > > > > > What's the difference between doing the above and this? > > > > > > > > > > > > if (didRemove) > > > > > > removeFinishedSourceNodes(); > > > > > > > > > > > > Furthermore, I am not sure how this change helps in fixing the > problem. > > > > > > > > > > Mostly less duplication in the two places that call this. > > > > > > > > > > By moving the remove outside the tryLock, we're not inside the graph > lock > > > when > > > > > removeFinishedSourceNodesOnMainThread is run which tries to grab the > lock > > on > > > > the > > > > > main thread. I think before removeFinishedSourceNodes could run on the > > main > > > > > thread while the tryLock was still active (holding on to the graph > lock). > > > So > > > > > two different threads were contending for the same lock, but the calls > are > > > in > > > > a > > > > > cycle. > > > > > > > > What I meant by the comment above is: why do we have to pass |didRemove| > to > > > the > > > > function? > > > > > > Just to make the logic of what to do with didRemove the same so the caller > > > doesn't need to do the check. I'm fine having the check in the caller or > the > > > callee. > > > > > > > > > > > What's the scope of tryLock() here? Is it inside of the if statement? Or > up > > to > > > > the end of handlePostRenderTasks()? > > > > > > Since there's an unlock() at line 762, the lock ends at the end of the if > > > (tryLock()) block. > > > > > > > > > > Okay, probably this will be the last question; can we move source nodes > handling > > logic to DFH? All other post-render tasks are handled by DFH, not the context. > > Let me try. You mean DeferredTaskHandler? (Not sure what DFH is). > But I don't quite follow the DFH comment since releaseFinishedSourceNodes is in > BaseAudioContext, DeferredTaskHandler. Sorry. Yes, I meant DTH. I am naively asking why 'finished source nodes' got to stay in the context while other 'deferrable' tasks are in the DTH.
On 2017/01/23 18:15:21, hongchan wrote: > On 2017/01/23 18:11:21, Raymond Toy wrote: > > > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > > File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp (right): > > > > > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > > third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: > > removeFinishedSourceNodes(didRemove); > > On 2017/01/23 18:08:06, hongchan wrote: > > > On 2017/01/23 17:45:01, Raymond Toy wrote: > > > > On 2017/01/23 17:38:41, hongchan wrote: > > > > > On 2017/01/21 00:12:15, Raymond Toy wrote: > > > > > > On 2017/01/20 23:27:05, hongchan wrote: > > > > > > > What's the difference between doing the above and this? > > > > > > > > > > > > > > if (didRemove) > > > > > > > removeFinishedSourceNodes(); > > > > > > > > > > > > > > Furthermore, I am not sure how this change helps in fixing the > > problem. > > > > > > > > > > > > Mostly less duplication in the two places that call this. > > > > > > > > > > > > By moving the remove outside the tryLock, we're not inside the graph > > lock > > > > when > > > > > > removeFinishedSourceNodesOnMainThread is run which tries to grab the > > lock > > > on > > > > > the > > > > > > main thread. I think before removeFinishedSourceNodes could run on > the > > > main > > > > > > thread while the tryLock was still active (holding on to the graph > > lock). > > > > So > > > > > > two different threads were contending for the same lock, but the calls > > are > > > > in > > > > > a > > > > > > cycle. > > > > > > > > > > What I meant by the comment above is: why do we have to pass |didRemove| > > to > > > > the > > > > > function? > > > > > > > > Just to make the logic of what to do with didRemove the same so the caller > > > > doesn't need to do the check. I'm fine having the check in the caller or > > the > > > > callee. > > > > > > > > > > > > > > What's the scope of tryLock() here? Is it inside of the if statement? Or > > up > > > to > > > > > the end of handlePostRenderTasks()? > > > > > > > > Since there's an unlock() at line 762, the lock ends at the end of the if > > > > (tryLock()) block. > > > > > > > > > > > > > > Okay, probably this will be the last question; can we move source nodes > > handling > > > logic to DFH? All other post-render tasks are handled by DFH, not the > context. > > > > Let me try. You mean DeferredTaskHandler? (Not sure what DFH is). > > But I don't quite follow the DFH comment since releaseFinishedSourceNodes is > in > > BaseAudioContext, DeferredTaskHandler. > > Sorry. Yes, I meant DTH. I am naively asking why 'finished source nodes' got to > stay in the context while other 'deferrable' tasks are in the DTH. Most likely because the member variables that are needed live in the context not the handler. Perhaps these variables don't really make sense in the DTH?
On 2017/01/23 18:17:34, Raymond Toy wrote: > On 2017/01/23 18:15:21, hongchan wrote: > > On 2017/01/23 18:11:21, Raymond Toy wrote: > > > > > > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > > > File third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp > (right): > > > > > > > > > https://codereview.chromium.org/2638413004/diff/20001/third_party/WebKit/Sour... > > > third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp:765: > > > removeFinishedSourceNodes(didRemove); > > > On 2017/01/23 18:08:06, hongchan wrote: > > > > On 2017/01/23 17:45:01, Raymond Toy wrote: > > > > > On 2017/01/23 17:38:41, hongchan wrote: > > > > > > On 2017/01/21 00:12:15, Raymond Toy wrote: > > > > > > > On 2017/01/20 23:27:05, hongchan wrote: > > > > > > > > What's the difference between doing the above and this? > > > > > > > > > > > > > > > > if (didRemove) > > > > > > > > removeFinishedSourceNodes(); > > > > > > > > > > > > > > > > Furthermore, I am not sure how this change helps in fixing the > > > problem. > > > > > > > > > > > > > > Mostly less duplication in the two places that call this. > > > > > > > > > > > > > > By moving the remove outside the tryLock, we're not inside the graph > > > lock > > > > > when > > > > > > > removeFinishedSourceNodesOnMainThread is run which tries to grab the > > > lock > > > > on > > > > > > the > > > > > > > main thread. I think before removeFinishedSourceNodes could run on > > the > > > > main > > > > > > > thread while the tryLock was still active (holding on to the graph > > > lock). > > > > > So > > > > > > > two different threads were contending for the same lock, but the > calls > > > are > > > > > in > > > > > > a > > > > > > > cycle. > > > > > > > > > > > > What I meant by the comment above is: why do we have to pass > |didRemove| > > > to > > > > > the > > > > > > function? > > > > > > > > > > Just to make the logic of what to do with didRemove the same so the > caller > > > > > doesn't need to do the check. I'm fine having the check in the caller > or > > > the > > > > > callee. > > > > > > > > > > > > > > > > > What's the scope of tryLock() here? Is it inside of the if statement? > Or > > > up > > > > to > > > > > > the end of handlePostRenderTasks()? > > > > > > > > > > Since there's an unlock() at line 762, the lock ends at the end of the > if > > > > > (tryLock()) block. > > > > > > > > > > > > > > > > > > Okay, probably this will be the last question; can we move source nodes > > > handling > > > > logic to DFH? All other post-render tasks are handled by DFH, not the > > context. > > > > > > Let me try. You mean DeferredTaskHandler? (Not sure what DFH is). > > > But I don't quite follow the DFH comment since releaseFinishedSourceNodes > is > > in > > > BaseAudioContext, DeferredTaskHandler. > > > > Sorry. Yes, I meant DTH. I am naively asking why 'finished source nodes' got > to > > stay in the context while other 'deferrable' tasks are in the DTH. > > Most likely because the member variables that are needed live in the context not > the handler. Perhaps these variables don't really make sense in the DTH? From a quick offline discussion, moving these things around is a separate issue, not directly related to fixing the lock order issue. Thus, that refactoring is a different CL.
lgtm
The CQ bit was checked by rtoy@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
CQ is committing da patch.
Bot data: {"patchset_id": 20001, "attempt_start_ts": 1485196001419170,
"parent_rev": "421a2db9f7cb0ff46bd0d1a89f9ab314737b7308", "commit_rev":
"b82438a6b9cf9324f9d2b3780ea270b7bff62a93"}
Message was sent while issue was closed.
Description was changed from ========== Don't run removeFinishedSourceNodes with the context lock. releaseFinishedSourceNodes is run from handlePostRenderTask on the audio thread which has the context lock. releaseFinishedSourceNodes can call removeFinishedSourceNodes which runs on the main thread which will also get the context lock. Depending on how fast things are, this second attempt to get the lock may happen while handlePostRenderTask still has the lock, causing a cycle. Therefore, move the call to removeFinishedSourceNodes outside the lock. This is ok, since removeFinishedSourceNodes doesn't do anything without acquiring the context lock. BUG=681316 TEST=test case from the bug passes on a tsan build ========== to ========== Don't run removeFinishedSourceNodes with the context lock. releaseFinishedSourceNodes is run from handlePostRenderTask on the audio thread which has the context lock. releaseFinishedSourceNodes can call removeFinishedSourceNodes which runs on the main thread which will also get the context lock. Depending on how fast things are, this second attempt to get the lock may happen while handlePostRenderTask still has the lock, causing a cycle. Therefore, move the call to removeFinishedSourceNodes outside the lock. This is ok, since removeFinishedSourceNodes doesn't do anything without acquiring the context lock. BUG=681316 TEST=test case from the bug passes on a tsan build Review-Url: https://codereview.chromium.org/2638413004 Cr-Commit-Position: refs/heads/master@{#445467} Committed: https://chromium.googlesource.com/chromium/src/+/b82438a6b9cf9324f9d2b3780ea2... ==========
Message was sent while issue was closed.
Committed patchset #2 (id:20001) as https://chromium.googlesource.com/chromium/src/+/b82438a6b9cf9324f9d2b3780ea2... |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
