Changeset 238250 in webkit


Ignore:
Timestamp:
Nov 15, 2018 2:01:31 PM (5 years ago)
Author:
Chris Dumez
Message:

IndexedDB.IndexedDBTempFileSize API test times out with process prewarming enabled
https://bugs.webkit.org/show_bug.cgi?id=191671
<rdar://problem/46086062>

Reviewed by Alex Christensen.

Source/WebKit:

Enabling process prewarming caused IndexedDB.IndexedDBTempFileSize API to time out and print
the following line:
"Attempted to create a NetworkLoad with a session (id=2) that does not exist."

This actually identified a pre-existing bug with our handling of non-default data store.
Whenever a page starts using a data store, we call WebProcessPool::pageBeginUsingWebsiteDataStore()
which will call NetworkProcessProxy::addSession() if the network process was already started
to let the network process know about this non-default session. There are several issues with the
current model:

  1. If the network process was not created yet when pageBeginUsingWebsiteDataStore() is called, then the network process will not know about the non-default session when it actually gets started later on. This is unlikely to happen in practice, except in case of network process crash because we create the network process as soon as we initialize the first WebProcessProxy.
  2. Even if we successfuly managed to register the session with the network process proxy, we get in trouble if the network process crashes or is terminated later on as we do not re-register those sessions with the new network process.

To address these 2 issues, WebProcessPool::ensureNetworkProcess() now takes care of registering
all the non-default sessions (that are associated with this process pool) with the new network
process. The WebProcessPool knows about these sessions because it adds them to m_sessionToPagesMap
whenever WebProcessPool::pageBeginUsingWebsiteDataStore() is called, even if the network process
proxy was not created yet.

The reason the IndexedDB.IndexedDBTempFileSize API test was failing was because it did:

  1. A load in a WebView V1 with a non-default session
  2. Process prewarming kicked in after this load and would create a new WebProcessProxy.
  3. Terminate the network process
  4. Another load in a WebView V2 with the same non-defaut session, which would reuse the prewarmed process. Because the network process was terminated, constructing the new page would not register the session ID with the new network process when pageBeginUsingWebsiteDataStore() is called.

-> The load would hang because the new network process would not know about the

non-default session when started later on.

The bug was previously hidden without process prewarming because step 4 would create a *new*
WebProcessProxy and WebProcessPool::initializeNewWebProcess() would call ensureNetworkProcess()
so that pageBeginUsingWebsiteDataStore() would successfuly register the session with the
network process later on.

I wrote a second API test (WebKit.DoLoadWithNonDefaultDataStoreAfterTerminatingNetworkProcess)
to demonstrate the pre-existing bug without process prewarming enabled.

  • UIProcess/WebProcessPool.cpp:

(WebKit::WebProcessPool::ensureNetworkProcess):

Tools:

Add API test coverage.

  • TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
  • TestWebKitAPI/Tests/WebKitCocoa/WebsiteDataStoreCustomPaths.mm:

(TEST):

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r238249 r238250  
     12018-11-15  Chris Dumez  <cdumez@apple.com>
     2
     3        IndexedDB.IndexedDBTempFileSize API test times out with process prewarming enabled
     4        https://bugs.webkit.org/show_bug.cgi?id=191671
     5        <rdar://problem/46086062>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Enabling process prewarming caused IndexedDB.IndexedDBTempFileSize API to time out and print
     10        the following line:
     11        "Attempted to create a NetworkLoad with a session (id=2) that does not exist."
     12
     13        This actually identified a pre-existing bug with our handling of non-default data store.
     14        Whenever a page starts using a data store, we call WebProcessPool::pageBeginUsingWebsiteDataStore()
     15        which will call NetworkProcessProxy::addSession() if the network process was already started
     16        to let the network process know about this non-default session. There are several issues with the
     17        current model:
     18        1. If the network process was not created yet when pageBeginUsingWebsiteDataStore() is called,
     19           then the network process will not know about the non-default session when it actually gets
     20           started later on. This is unlikely to happen in practice, except in case of network process
     21           crash because we create the network process as soon as we initialize the first WebProcessProxy.
     22        2. Even if we successfuly managed to register the session with the network process proxy, we get
     23           in trouble if the network process crashes or is terminated later on as we do not re-register
     24           those sessions with the new network process.
     25
     26        To address these 2 issues, WebProcessPool::ensureNetworkProcess() now takes care of registering
     27        all the non-default sessions (that are associated with this process pool) with the new network
     28        process. The WebProcessPool knows about these sessions because it adds them to m_sessionToPagesMap
     29        whenever WebProcessPool::pageBeginUsingWebsiteDataStore() is called, even if the network process
     30        proxy was not created yet.
     31
     32        The reason the IndexedDB.IndexedDBTempFileSize API test was failing was because it did:
     33        1. A load in a WebView V1 with a non-default session
     34        2. Process prewarming kicked in after this load and would create a new WebProcessProxy.
     35        3. Terminate the network process
     36        4. Another load in a WebView V2 with the same non-defaut session, which would reuse the
     37          prewarmed process. Because the network process was terminated, constructing the new
     38          page would not register the session ID with the new network process when
     39          pageBeginUsingWebsiteDataStore() is called.
     40        -> The load would hang because the new network process would not know about the
     41           non-default session when started later on.
     42
     43        The bug was previously hidden without process prewarming because step 4 would create a *new*
     44        WebProcessProxy and WebProcessPool::initializeNewWebProcess() would call ensureNetworkProcess()
     45        so that pageBeginUsingWebsiteDataStore() would successfuly register the session with the
     46        network process later on.
     47
     48        I wrote a second API test (WebKit.DoLoadWithNonDefaultDataStoreAfterTerminatingNetworkProcess)
     49        to demonstrate the pre-existing bug without process prewarming enabled.
     50
     51        * UIProcess/WebProcessPool.cpp:
     52        (WebKit::WebProcessPool::ensureNetworkProcess):
     53
    1542018-11-15  Vivek Seth  <v_seth@apple.com>
    255
  • trunk/Source/WebKit/UIProcess/WebProcessPool.cpp

    r238248 r238250  
    569569    }
    570570
     571    // Make sure the network process knowns about all the sessions that have been registered before it started.
     572    for (auto& sessionID : m_sessionToPagesMap.keys()) {
     573        if (auto* websiteDataStore = WebsiteDataStore::existingNonDefaultDataStoreForSessionID(sessionID))
     574            m_networkProcess->addSession(*websiteDataStore);
     575    }
     576
    571577    if (m_websiteDataStore)
    572578        m_websiteDataStore->websiteDataStore().didCreateNetworkProcess();
  • trunk/Tools/ChangeLog

    r238244 r238250  
     12018-11-15  Chris Dumez  <cdumez@apple.com>
     2
     3        IndexedDB.IndexedDBTempFileSize API test times out with process prewarming enabled
     4        https://bugs.webkit.org/show_bug.cgi?id=191671
     5        <rdar://problem/46086062>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Add API test coverage.
     10
     11        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
     12        * TestWebKitAPI/Tests/WebKitCocoa/WebsiteDataStoreCustomPaths.mm:
     13        (TEST):
     14
    1152018-11-15  Oriol Brufau  <obrufau@igalia.com>
    216
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

    r238216 r238250  
    26912691}
    26922692
     2693TEST(ProcessSwap, UsePrewarmedProcessAfterTerminatingNetworkProcess)
     2694{
     2695    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
     2696    processPoolConfiguration.get().processSwapsOnNavigation = YES;
     2697    processPoolConfiguration.get().prewarmsProcessesAutomatically = YES;
     2698    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
     2699
     2700    auto websiteDataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]);
     2701
     2702    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     2703    [webViewConfiguration setProcessPool:processPool.get()];
     2704    webViewConfiguration.get().websiteDataStore = [[[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()] autorelease];
     2705
     2706    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     2707    auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
     2708    [webView setNavigationDelegate:delegate.get()];
     2709
     2710    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
     2711    [webView loadRequest:request];
     2712
     2713    TestWebKitAPI::Util::run(&done);
     2714    done = false;
     2715
     2716    TestWebKitAPI::Util::spinRunLoop(1);
     2717
     2718    [processPool _terminateNetworkProcess];
     2719
     2720    auto webView2 = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     2721    [webView2 setNavigationDelegate:delegate.get()];
     2722    request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
     2723    [webView2 loadRequest:request];
     2724
     2725    TestWebKitAPI::Util::run(&done);
     2726    done = false;
     2727}
     2728
    26932729#if PLATFORM(MAC)
    26942730
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebsiteDataStoreCustomPaths.mm

    r238215 r238250  
    2828#import "PlatformUtilities.h"
    2929#import "Test.h"
    30 #import <WebKit/WebKit.h>
    31 
     30#import "TestNavigationDelegate.h"
    3231#import <WebKit/WKProcessPoolPrivate.h>
    3332#import <WebKit/WKUserContentControllerPrivate.h>
     
    3534#import <WebKit/WKWebViewPrivate.h>
    3635#import <WebKit/WKWebsiteDataStorePrivate.h>
     36#import <WebKit/WebKit.h>
    3737#import <WebKit/_WKProcessPoolConfiguration.h>
    3838#import <WebKit/_WKUserStyleSheet.h>
     
    427427}
    428428
     429TEST(WebKit, DoLoadWithNonDefaultDataStoreAfterTerminatingNetworkProcess)
     430{
     431    auto websiteDataStoreConfiguration = adoptNS([[_WKWebsiteDataStoreConfiguration alloc] init]);
     432
     433    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     434    webViewConfiguration.get().websiteDataStore = [[[WKWebsiteDataStore alloc] _initWithConfiguration:websiteDataStoreConfiguration.get()] autorelease];
     435
     436    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     437
     438    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
     439    [webView loadRequest:request];
     440    [webView _test_waitForDidFinishNavigation];
     441
     442    TestWebKitAPI::Util::spinRunLoop(1);
     443
     444    [webViewConfiguration.get().processPool _terminateNetworkProcess];
     445
     446    request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"simple2" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
     447    [webView loadRequest:request];
     448    [webView _test_waitForDidFinishNavigation];
     449}
     450
    429451#endif
Note: See TracChangeset for help on using the changeset viewer.