Bug 224704 - LibWebRTCCodecs eagerly launches the GPUProcess and always relaunches it on exit
Summary: LibWebRTCCodecs eagerly launches the GPUProcess and always relaunches it on exit
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Media (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Chris Dumez
URL:
Keywords: InRadar
Depends on: 224758
Blocks: 224709
  Show dependency treegraph
 
Reported: 2021-04-16 16:33 PDT by Chris Dumez
Modified: 2021-04-24 15:06 PDT (History)
11 users (show)

See Also:


Attachments
Patch (11.65 KB, patch)
2021-04-16 18:15 PDT, Chris Dumez
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (11.94 KB, patch)
2021-04-16 18:22 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (12.58 KB, patch)
2021-04-16 19:45 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (13.22 KB, patch)
2021-04-16 19:51 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (14.04 KB, patch)
2021-04-17 15:51 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (14.04 KB, patch)
2021-04-17 15:54 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-16 16:33:14 PDT
LibWebRTCCodecs eagerly launches the GPUProcess and always relaunches it on exit. The GPUProcess should only be (re-)launched when needed. In the case of the LibWebRTCCodecs, it seems it only needs a GPUProcess connection if it has m_decoders / m_encoders are non-empty.
Comment 1 Chris Dumez 2021-04-16 18:15:53 PDT
Created attachment 426303 [details]
Patch
Comment 2 Chris Dumez 2021-04-16 18:22:10 PDT
Created attachment 426304 [details]
Patch
Comment 3 Chris Dumez 2021-04-16 18:57:07 PDT
Looks like WebKit2.CrashGPUProcessWhileCapturingAndCalling is failing. I will need to investigate.
Comment 4 Chris Dumez 2021-04-16 19:45:39 PDT
Created attachment 426312 [details]
Patch
Comment 5 Chris Dumez 2021-04-16 19:51:49 PDT
Created attachment 426314 [details]
Patch
Comment 6 Darin Adler 2021-04-17 15:28:18 PDT
Comment on attachment 426314 [details]
Patch

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

> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:172
> +void LibWebRTCCodecs::ensureGPUProcessConnectionOnMainThread(Locker<Lock>&)

Just idly wondering: Would you want to add something like this?

    ASSERT_UNUSED(locker, locker.lockable() == &m_connectionLock);

Adding that would require adding a lockable() member function to the Locker class template.

> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:496
> +    std::exchange(m_connection, nullptr)->removeThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName());

Is there a firm guarantee that m_connection is always non-null here? No race or edge case where it could be null?

> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h:68
> +    static Ref<LibWebRTCCodecs> create()
>      {
> -        auto instance = std::unique_ptr<LibWebRTCCodecs>(new LibWebRTCCodecs);
> -        instance->startListeningForIPC();
> -        return instance;
> +        return adoptRef(*new LibWebRTCCodecs);
>      }

This shouldn’t be inlined. I suggest moving it out of the header file. Normally it’s better that we inline the call to the constructor, and have the call to this create function be a normal function call. And it also reduces churn in the header file a little.
Comment 7 Chris Dumez 2021-04-17 15:32:25 PDT
Comment on attachment 426314 [details]
Patch

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

>> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:172
>> +void LibWebRTCCodecs::ensureGPUProcessConnectionOnMainThread(Locker<Lock>&)
> 
> Just idly wondering: Would you want to add something like this?
> 
>     ASSERT_UNUSED(locker, locker.lockable() == &m_connectionLock);
> 
> Adding that would require adding a lockable() member function to the Locker class template.

Ok

>> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.cpp:496
>> +    std::exchange(m_connection, nullptr)->removeThreadMessageReceiver(Messages::LibWebRTCCodecs::messageReceiverName());
> 
> Is there a firm guarantee that m_connection is always non-null here? No race or edge case where it could be null?

gpuProcessConnectionDidClose() can only get called if we registered ourselves as a client of the connection. This happens in ensureGPUProcessConnectionOnMainThread() and we initialize m_connection then.
m_connection is only cleared here in gpuProcessConnectionDidClose() and gpuProcessConnectionDidClose() can only be called one time per connection. I believe this is safe.

>> Source/WebKit/WebProcess/GPU/webrtc/LibWebRTCCodecs.h:68
>>      }
> 
> This shouldn’t be inlined. I suggest moving it out of the header file. Normally it’s better that we inline the call to the constructor, and have the call to this create function be a normal function call. And it also reduces churn in the header file a little.

OK.
Comment 8 Chris Dumez 2021-04-17 15:51:38 PDT
Created attachment 426354 [details]
Patch
Comment 9 Chris Dumez 2021-04-17 15:54:13 PDT
Created attachment 426355 [details]
Patch
Comment 10 EWS 2021-04-17 17:10:20 PDT
Committed r276214 (236696@main): <https://commits.webkit.org/236696@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 426355 [details].
Comment 11 youenn fablet 2021-04-19 02:25:49 PDT
This patch probably introduces some races, for instance:
- creation of the encoder is now sometimes doing: webrtc thread -> main thread -> codec thread.
- deletion of the encoder is doing: webrtc thread -> codec thread.
We might sometimes delete the encoder before it is actually added in the map.
Ditto for decoder creation/deletion.

The same applies for init of the encoder:
- creation of the encoder is now doing: webrtc thread -> main thread -> codec thread.
- initialisation of the encoder is doing: webrtc thread -> encoder thread.

We should probably fix these issues.
Simplest approach is probably to always do "webrtc thread -> main thread -> codec thread" for encoder creation/initialization/deletion and decoder creation/deletion.

We also widen the interval where we might miss decoding/encoding frames due to connection not be set yet.
This is pre-existing and is probably fine since this might not happen often in practice.
Comment 12 Chris Dumez 2021-04-19 07:48:12 PDT
(In reply to youenn fablet from comment #11)
> This patch probably introduces some races, for instance:
> - creation of the encoder is now sometimes doing: webrtc thread -> main
> thread -> codec thread.
> - deletion of the encoder is doing: webrtc thread -> codec thread.
> We might sometimes delete the encoder before it is actually added in the map.
> Ditto for decoder creation/deletion.
> 
> The same applies for init of the encoder:
> - creation of the encoder is now doing: webrtc thread -> main thread ->
> codec thread.
> - initialisation of the encoder is doing: webrtc thread -> encoder thread.
> 
> We should probably fix these issues.
> Simplest approach is probably to always do "webrtc thread -> main thread ->
> codec thread" for encoder creation/initialization/deletion and decoder
> creation/deletion.
> 
> We also widen the interval where we might miss decoding/encoding frames due
> to connection not be set yet.
> This is pre-existing and is probably fine since this might not happen often
> in practice.

Thanks for checking the patch and finding this out. I agree this is racy. I will follow-up shortly.
Comment 13 Radar WebKit Bug Importer 2021-04-24 15:06:44 PDT
<rdar://problem/77110079>