Bug 224758 - Fix races in LibWebRTCCodecs introduced in r276214
Summary: Fix races in LibWebRTCCodecs introduced in r276214
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit2 (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Chris Dumez
URL:
Keywords: InRadar
Depends on:
Blocks: 224704
  Show dependency treegraph
 
Reported: 2021-04-19 07:49 PDT by Chris Dumez
Modified: 2021-04-23 03:01 PDT (History)
5 users (show)

See Also:


Attachments
Patch (3.75 KB, patch)
2021-04-19 07:52 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (5.82 KB, patch)
2021-04-19 09:24 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (5.72 KB, patch)
2021-04-19 09:53 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Dumez 2021-04-19 07:49:04 PDT
Fix races in LibWebRTCCodecs introduced in r276214.
Comment 1 Chris Dumez 2021-04-19 07:52:47 PDT
Created attachment 426418 [details]
Patch
Comment 2 youenn fablet 2021-04-19 08:42:16 PDT
Comment on attachment 426418 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=426418&action=review

> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:262
> +    ensureGPUProcessConnectionAndDispatchToThread([this, decoderIdentifier = decoder.identifier] {

Maybe add a comment in ensureGPUProcessConnectionAndDispatchToThread that the m_connection lock needs to be kept for the dispatchToThread call in ensureGPUProcessConnectionAndDispatchToThread/ensureOnMainRunLoop.

Also, let's look at the following case:
- createEncoder goes to main thread as connection is null.
- initializeEncoder goes to main thread as connection is null.
- createEncoder callback is in main thread, creates the connection, goes to the codec queue.
- releaseEncoder goes to the codec queue as connection is no longer null.
- initializeEncoder callback is in the main thread and goes to the codec queue.

We probably can have initializeEncoder happening after releaseEncoder in the codec queue.

We could accept the raciness of initializeEncoder, and add a if(auto* encoder...) in its implementation.
We could also store a goThroughMainThread state in encoder/decoder structures, less subtle and probably stronger.
Comment 3 Chris Dumez 2021-04-19 08:53:33 PDT
(In reply to youenn fablet from comment #2)
> Comment on attachment 426418 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=426418&action=review
> 
> > Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:262
> > +    ensureGPUProcessConnectionAndDispatchToThread([this, decoderIdentifier = decoder.identifier] {
> 
> Maybe add a comment in ensureGPUProcessConnectionAndDispatchToThread that
> the m_connection lock needs to be kept for the dispatchToThread call in
> ensureGPUProcessConnectionAndDispatchToThread/ensureOnMainRunLoop.
> 
> Also, let's look at the following case:
> - createEncoder goes to main thread as connection is null.
> - initializeEncoder goes to main thread as connection is null.
> - createEncoder callback is in main thread, creates the connection, goes to
> the codec queue.
> - releaseEncoder goes to the codec queue as connection is no longer null.
> - initializeEncoder callback is in the main thread and goes to the codec
> queue.
> 
> We probably can have initializeEncoder happening after releaseEncoder in the
> codec queue.
> 
> We could accept the raciness of initializeEncoder, and add a if(auto*
> encoder...) in its implementation.

Even that wouldn't be safe I think. You could imagine createDecoder getting called first, then createEncoder, then initializeEncoder in your scenario. initializeEncoder would get received before createEncoder which would be bad.

> We could also store a goThroughMainThread state in encoder/decoder
> structures, less subtle and probably stronger.
Comment 4 Chris Dumez 2021-04-19 09:18:53 PDT
(In reply to Chris Dumez from comment #3)
> (In reply to youenn fablet from comment #2)
> > Comment on attachment 426418 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=426418&action=review
> > 
> > > Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:262
> > > +    ensureGPUProcessConnectionAndDispatchToThread([this, decoderIdentifier = decoder.identifier] {
> > 
> > Maybe add a comment in ensureGPUProcessConnectionAndDispatchToThread that
> > the m_connection lock needs to be kept for the dispatchToThread call in
> > ensureGPUProcessConnectionAndDispatchToThread/ensureOnMainRunLoop.
> > 
> > Also, let's look at the following case:
> > - createEncoder goes to main thread as connection is null.
> > - initializeEncoder goes to main thread as connection is null.
> > - createEncoder callback is in main thread, creates the connection, goes to
> > the codec queue.
> > - releaseEncoder goes to the codec queue as connection is no longer null.
> > - initializeEncoder callback is in the main thread and goes to the codec
> > queue.
> > 
> > We probably can have initializeEncoder happening after releaseEncoder in the
> > codec queue.
> > 
> > We could accept the raciness of initializeEncoder, and add a if(auto*
> > encoder...) in its implementation.
> 
> Even that wouldn't be safe I think. You could imagine createDecoder getting
> called first, then createEncoder, then initializeEncoder in your scenario.
> initializeEncoder would get received before createEncoder which would be bad.

I have a proposal that would address that. I am polishing the patch and will upload shortly.
Comment 5 Chris Dumez 2021-04-19 09:24:42 PDT
Created attachment 426433 [details]
Patch
Comment 6 youenn fablet 2021-04-19 09:42:54 PDT
Comment on attachment 426433 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=426433&action=review

> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:202
> +    if (m_connection) {

I would put that first since this is the fast path.

> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:213
> +            dispatchToThread(m_tasksToDispatchAfterEstablishingConnection.takeFirst());

Seems like we could use a Vector.
Comment 7 Chris Dumez 2021-04-19 09:53:36 PDT
Created attachment 426437 [details]
Patch
Comment 8 EWS 2021-04-19 10:53:11 PDT
Committed r276263 (236745@main): <https://commits.webkit.org/236745@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 426437 [details].
Comment 9 Ling Ho 2021-04-23 03:01:28 PDT
rdar://76852677