Bug 238570 - Do not create network process in ~WebsiteDataStore destructor
Summary: Do not create network process in ~WebsiteDataStore destructor
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit2 (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Yury Semikhatsky
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2022-03-30 12:39 PDT by Yury Semikhatsky
Modified: 2022-04-05 11:00 PDT (History)
7 users (show)

See Also:


Attachments
Patch (1.72 KB, patch)
2022-03-30 12:43 PDT, Yury Semikhatsky
no flags Details | Formatted Diff | Diff
Patch (3.82 KB, patch)
2022-04-01 00:30 PDT, Yury Semikhatsky
no flags Details | Formatted Diff | Diff
Patch (3.79 KB, patch)
2022-04-05 09:54 PDT, Yury Semikhatsky
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Yury Semikhatsky 2022-03-30 12:39:00 PDT
Do not create network process in ~WebsiteDataStore destructor
Comment 1 Yury Semikhatsky 2022-03-30 12:43:36 PDT
Created attachment 456166 [details]
Patch
Comment 2 Darin Adler 2022-03-30 14:35:49 PDT
Comment on attachment 456166 [details]
Patch

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

Great fix! We really want this.

> Source/WebKit/ChangeLog:13
> +        No new tests.

Can we make a test? Normally the project requires a test for an bug fix.
Comment 3 Yury Semikhatsky 2022-03-30 15:33:37 PDT
> Can we make a test? Normally the project requires a test for an bug fix.

The bug manifested itself as WPENetworkProcess running after corresponding WebsiteDataStore has been closed so I don't think there is a way to test it in a layout test. I tried to come up with a unit test but there is no API for getting currently running network processes. Do you have an advice on how that could be tested via WebKit API?
Comment 4 Darin Adler 2022-03-30 15:55:08 PDT
In past in such cases we have typically added calls as needed to test such things. Like add something to count network processes.
Comment 5 Darin Adler 2022-03-30 15:55:30 PDT
Chris, do you have suggestions on how to make a test? You’ve fixed many bugs like this one. Or maybe you know someone else we should ask.
Comment 6 Chris Dumez 2022-03-30 16:00:57 PDT
Comment on attachment 456166 [details]
Patch

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

>> Source/WebKit/ChangeLog:13
>> +        No new tests.
> 
> Can we make a test? Normally the project requires a test for an bug fix.

I would look at the NetworkProcess.LaunchOnlyWhenNecessary for example. Not sure if this is practical in this particular case. I am in the middle of something but can look into it a bit later if needed.
Comment 7 Chris Dumez 2022-03-30 16:39:46 PDT
(In reply to Chris Dumez from comment #6)
> Comment on attachment 456166 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=456166&action=review
> 
> >> Source/WebKit/ChangeLog:13
> >> +        No new tests.
> > 
> > Can we make a test? Normally the project requires a test for an bug fix.
> 
> I would look at the NetworkProcess.LaunchOnlyWhenNecessary for example. Not
> sure if this is practical in this particular case. I am in the middle of
> something but can look into it a bit later if needed.

I think something like this might do the trick (but please verify):
```
TEST(NetworkProcess, DoNotLaunchOnDataStoreDestruction)
{
    EXPECT_FALSE([WKWebsiteDataStore _defaultDataStoreExists]);
    @autoreleasepool {
        auto storeConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] initNonPersistentConfiguration]);
        auto websiteDataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration: storeConfiguration.get()]);
    }

    TestWebKitAPI::Util::spinRunLoop(10);
    EXPECT_FALSE([WKWebsiteDataStore _defaultDataStoreExists]);
}
```
Comment 8 Sihui Liu 2022-03-30 16:55:20 PDT
Comment on attachment 456166 [details]
Patch

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

>>>> Source/WebKit/ChangeLog:13
>>>> +        No new tests.
>>> 
>>> Can we make a test? Normally the project requires a test for an bug fix.
>> 
>> I would look at the NetworkProcess.LaunchOnlyWhenNecessary for example. Not sure if this is practical in this particular case. I am in the middle of something but can look into it a bit later if needed.
> 
> I think something like this might do the trick (but please verify):
> ```
> TEST(NetworkProcess, DoNotLaunchOnDataStoreDestruction)
> {
>     EXPECT_FALSE([WKWebsiteDataStore _defaultDataStoreExists]);
>     @autoreleasepool {
>         auto storeConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] initNonPersistentConfiguration]);
>         auto websiteDataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration: storeConfiguration.get()]);
>     }
> 
>     TestWebKitAPI::Util::spinRunLoop(10);
>     EXPECT_FALSE([WKWebsiteDataStore _defaultDataStoreExists]);
> }
> ```

How about creating a custom persistent WKWebsiteDataStore, destroying it, and checking if default network process exists?
@autoreleasepool {
    auto websiteDataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]);
    auto websiteDataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()]).get();
}
TestWebKitAPI::Util::spinRunLoop(10); // Is this needed?
EXPECT_FALSE([WKWebsiteDataStore _defaultNetworkProcessExists]);

(please check if the test fails without fix)
Comment 9 Chris Dumez 2022-03-30 16:58:54 PDT
(In reply to Chris Dumez from comment #7)
> (In reply to Chris Dumez from comment #6)
> > Comment on attachment 456166 [details]
> > Patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=456166&action=review
> > 
> > >> Source/WebKit/ChangeLog:13
> > >> +        No new tests.
> > > 
> > > Can we make a test? Normally the project requires a test for an bug fix.
> > 
> > I would look at the NetworkProcess.LaunchOnlyWhenNecessary for example. Not
> > sure if this is practical in this particular case. I am in the middle of
> > something but can look into it a bit later if needed.
> 
> I think something like this might do the trick (but please verify):
> ```
> TEST(NetworkProcess, DoNotLaunchOnDataStoreDestruction)
> {
>     EXPECT_FALSE([WKWebsiteDataStore _defaultDataStoreExists]);
>     @autoreleasepool {
>         auto storeConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration
> alloc] initNonPersistentConfiguration]);
>         auto websiteDataStore = adoptNS([[WKWebsiteDataStore alloc]
> _initWithConfiguration: storeConfiguration.get()]);
>     }
> 
>     TestWebKitAPI::Util::spinRunLoop(10);
>     EXPECT_FALSE([WKWebsiteDataStore _defaultDataStoreExists]);
> }
> ```

Sihui pointed out I have a typo. I mean to check _defaultNetworkProcessExists above, not _defaultDataStoreExists.
Comment 10 Chris Dumez 2022-03-30 17:21:04 PDT
Comment on attachment 456166 [details]
Patch

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

> Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp:154
> +        m_networkProcess->removeSession(*this);

So the API test I wrote (and likely Sihui's) seems to pass without this fix. I believe the reason is that we launch the network process and then destroy it right away (unlike what the changelog claims).

We looked at it with Sihui and `networkProcess()` would indeed allocate a NetworkProcessProxy. However, the call to `removeSession()` would null out the default NetworkProcessProxy, which would cause the newly launched (likely still launching) process to exist right away.

Yury, I think it is good to fix either way but are you still the network process is indeed hanging around unnecessarily?
Comment 11 Chris Dumez 2022-03-30 17:24:28 PDT
(In reply to Chris Dumez from comment #10)
> Comment on attachment 456166 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=456166&action=review
> 
> > Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp:154
> > +        m_networkProcess->removeSession(*this);
> 
> So the API test I wrote (and likely Sihui's) seems to pass without this fix.
> I believe the reason is that we launch the network process and then destroy
> it right away (unlike what the changelog claims).
> 
> We looked at it with Sihui and `networkProcess()` would indeed allocate a
> NetworkProcessProxy. However, the call to `removeSession()` would null out
> the default NetworkProcessProxy, which would cause the newly launched
> (likely still launching) process to exist right away.

typo again: exist -> exit.
Comment 12 Chris Dumez 2022-03-30 17:28:39 PDT
Never mind, I was able to write an API test to cover this change:
```
TEST(NetworkProcess, DoNotLaunchOnDataStoreDestruction)
{
    auto storeConfiguration1 = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] initNonPersistentConfiguration]);
    auto websiteDataStore1 = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration: storeConfiguration1.get()]);

    EXPECT_FALSE([WKWebsiteDataStore _defaultNetworkProcessExists]);
    @autoreleasepool {
        auto storeConfiguration2 = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] initNonPersistentConfiguration]);
        auto websiteDataStore2 = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration: storeConfiguration2.get()]);
    }

    TestWebKitAPI::Util::spinRunLoop(10);
    EXPECT_FALSE([WKWebsiteDataStore _defaultNetworkProcessExists]);
}
```

Yury, do you mind incorporating it in your patch?
Comment 13 Yury Semikhatsky 2022-04-01 00:29:11 PDT
Comment on attachment 456166 [details]
Patch

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

> Yury, do you mind incorporating it in your patch?

Neat! I was looking for a hook that would give access to those in the linux ports but didn't find any, didn't consider the default network process accessor. In any case, I've added the test to the patch.

> Yury, I think it is good to fix either way but are you still the network process is indeed hanging around unnecessarily?

Originally I discovered the problem on linux where a new network process is launched for each ephemeral data store. The problem in GTK/WPE is that NetworkProxyProxy launches a new process
and gets destroyed immediately (as the only reference from WebsiteDataStore is removed), but the process itself keeps running until the browser is closed. Admittedly the process is properly killed
if at least one page was created with that WebsiteDataStore instance. I'd expect a network process to be terminated if its NetworkProcessProxy has been destroyed. Perhaps it's worth adding some logic
that would terminate the network process once its NetworkProcessProxy is destroyed.
Comment 14 Yury Semikhatsky 2022-04-01 00:30:17 PDT
Created attachment 456330 [details]
Patch
Comment 15 Yury Semikhatsky 2022-04-05 09:42:57 PDT
Darin, Chris, I've incorporated the test in the patch. Can you have another look?
Comment 16 Chris Dumez 2022-04-05 09:44:38 PDT
Comment on attachment 456330 [details]
Patch

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

r=me

> Source/WebKit/ChangeLog:13
> +        No new tests.

This is now a lie :)
Comment 17 Yury Semikhatsky 2022-04-05 09:54:55 PDT
Created attachment 456710 [details]
Patch
Comment 18 Yury Semikhatsky 2022-04-05 09:55:17 PDT
Comment on attachment 456330 [details]
Patch

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

>> Source/WebKit/ChangeLog:13
>> +        No new tests.
> 
> This is now a lie :)

Oops, fixed.
Comment 19 EWS 2022-04-05 10:59:57 PDT
Committed r292403 (249266@main): <https://commits.webkit.org/249266@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 456710 [details].
Comment 20 Radar WebKit Bug Importer 2022-04-05 11:00:22 PDT
<rdar://problem/91304176>