Changeset 282229 in webkit
- Timestamp:
- Sep 9, 2021, 11:04:35 AM (5 years ago)
- Location:
- branches/safari-612-branch
- Files:
-
- 12 edited
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/Shared/ProcessTerminationReason.h (modified) (1 diff)
-
Source/WebKit/UIProcess/API/C/WKAPICast.h (modified) (1 diff)
-
Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm (modified) (1 diff)
-
Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h (modified) (1 diff)
-
Source/WebKit/UIProcess/Cocoa/NavigationState.mm (modified) (1 diff)
-
Source/WebKit/UIProcess/WebPageProxy.cpp (modified) (10 diffs)
-
Source/WebKit/UIProcess/WebProcessPool.cpp (modified) (1 diff)
-
Source/WebKit/UIProcess/WebProcessProxy.cpp (modified) (8 diffs)
-
Source/WebKit/UIProcess/WebProcessProxy.h (modified) (2 diffs)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/safari-612-branch/Source/WebKit/ChangeLog
r282228 r282229 1 2021-09-09 Russell Epstein <repstein@apple.com> 2 3 Cherry-pick r282218. rdar://problem/82931375 4 5 Implement a WebProcess cap 6 https://bugs.webkit.org/show_bug.cgi?id=230067 7 <rdar://79479244> 8 9 Reviewed by Geoffrey Garen. 10 11 Source/WebKit: 12 13 Implement a WebProcess cap to avoid getting into a state where we run out of resources and crash in various ways. 14 The current limit is 400 and can be changed via an SPI. The limit is per UIProcess (not per process pool). 15 When we try and launch a new WebProcess and the limit has been reached, we terminate the least recently used 16 WebProcess to avoid going over the limit. 17 18 * Shared/ProcessTerminationReason.h: 19 * UIProcess/API/C/WKAPICast.h: 20 (WebKit::toAPI): 21 * UIProcess/API/Cocoa/WKProcessPool.mm: 22 (+[WKProcessPool _setWebProcessCountLimit:]): 23 * UIProcess/API/Cocoa/WKProcessPoolPrivate.h: 24 * UIProcess/Cocoa/NavigationState.mm: 25 (WebKit::wkProcessTerminationReason): 26 * UIProcess/WebPageProxy.cpp: 27 (WebKit::WebPageProxy::loadRequestWithNavigationShared): 28 (WebKit::WebPageProxy::loadFile): 29 (WebKit::WebPageProxy::loadDataWithNavigationShared): 30 (WebKit::WebPageProxy::loadSimulatedRequest): 31 (WebKit::WebPageProxy::loadAlternateHTML): 32 (WebKit::WebPageProxy::loadWebArchiveData): 33 (WebKit::WebPageProxy::reload): 34 (WebKit::WebPageProxy::goToBackForwardItem): 35 (WebKit::shouldReloadAfterProcessTermination): 36 * UIProcess/WebProcessProxy.cpp: 37 (WebKit::WebProcessProxy::setProcessCountLimit): 38 (WebKit::WebProcessProxy::create): 39 (WebKit::WebProcessProxy::~WebProcessProxy): 40 (WebKit::WebProcessProxy::addProvisionalPageProxy): 41 (WebKit::WebProcessProxy::addExistingWebPage): 42 (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch): 43 (WebKit::WebProcessProxy::establishServiceWorkerContext): 44 (WebKit::WebProcessProxy::markProcessAsRecentlyUsed): 45 * UIProcess/WebProcessProxy.h: 46 47 Tools: 48 49 Add API test coverage. 50 51 * TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm: 52 (TEST): 53 54 git-svn-id: https://svn.webkit.org/repository/webkit/trunk@282218 268f45cc-cd09-0410-ab3c-d52691b4dbfc 55 56 2021-09-09 Chris Dumez <cdumez@apple.com> 57 58 Implement a WebProcess cap 59 https://bugs.webkit.org/show_bug.cgi?id=230067 60 <rdar://79479244> 61 62 Reviewed by Geoffrey Garen. 63 64 Implement a WebProcess cap to avoid getting into a state where we run out of resources and crash in various ways. 65 The current limit is 400 and can be changed via an SPI. The limit is per UIProcess (not per process pool). 66 When we try and launch a new WebProcess and the limit has been reached, we terminate the least recently used 67 WebProcess to avoid going over the limit. 68 69 * Shared/ProcessTerminationReason.h: 70 * UIProcess/API/C/WKAPICast.h: 71 (WebKit::toAPI): 72 * UIProcess/API/Cocoa/WKProcessPool.mm: 73 (+[WKProcessPool _setWebProcessCountLimit:]): 74 * UIProcess/API/Cocoa/WKProcessPoolPrivate.h: 75 * UIProcess/Cocoa/NavigationState.mm: 76 (WebKit::wkProcessTerminationReason): 77 * UIProcess/WebPageProxy.cpp: 78 (WebKit::WebPageProxy::loadRequestWithNavigationShared): 79 (WebKit::WebPageProxy::loadFile): 80 (WebKit::WebPageProxy::loadDataWithNavigationShared): 81 (WebKit::WebPageProxy::loadSimulatedRequest): 82 (WebKit::WebPageProxy::loadAlternateHTML): 83 (WebKit::WebPageProxy::loadWebArchiveData): 84 (WebKit::WebPageProxy::reload): 85 (WebKit::WebPageProxy::goToBackForwardItem): 86 (WebKit::shouldReloadAfterProcessTermination): 87 * UIProcess/WebProcessProxy.cpp: 88 (WebKit::WebProcessProxy::setProcessCountLimit): 89 (WebKit::WebProcessProxy::create): 90 (WebKit::WebProcessProxy::~WebProcessProxy): 91 (WebKit::WebProcessProxy::addProvisionalPageProxy): 92 (WebKit::WebProcessProxy::addExistingWebPage): 93 (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch): 94 (WebKit::WebProcessProxy::establishServiceWorkerContext): 95 (WebKit::WebProcessProxy::markProcessAsRecentlyUsed): 96 * UIProcess/WebProcessProxy.h: 97 1 98 2021-09-09 Russell Epstein <repstein@apple.com> 2 99 -
branches/safari-612-branch/Source/WebKit/Shared/ProcessTerminationReason.h
r278895 r282229 31 31 ExceededMemoryLimit, 32 32 ExceededCPULimit, 33 ExceededProcessCountLimit, 33 34 RequestedByClient, 34 35 Crash, -
branches/safari-612-branch/Source/WebKit/UIProcess/API/C/WKAPICast.h
r274815 r282229 244 244 case ProcessTerminationReason::RequestedByClient: 245 245 return kWKProcessTerminationReasonRequestedByClient; 246 case ProcessTerminationReason::ExceededProcessCountLimit: 246 247 case ProcessTerminationReason::RequestedByNetworkProcess: 247 248 case ProcessTerminationReason::RequestedByGPUProcess: -
branches/safari-612-branch/Source/WebKit/UIProcess/API/Cocoa/WKProcessPool.mm
r282152 r282229 566 566 } 567 567 568 + (void)_setWebProcessCountLimit:(unsigned)limit 569 { 570 WebKit::WebProcessProxy::setProcessCountLimit(limit); 571 } 572 568 573 - (void)_garbageCollectJavaScriptObjectsForTesting 569 574 { -
branches/safari-612-branch/Source/WebKit/UIProcess/API/Cocoa/WKProcessPoolPrivate.h
r282152 r282229 74 74 + (pid_t)_webAuthnProcessIdentifier WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 75 75 76 + (void)_setWebProcessCountLimit:(unsigned)limit WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 77 76 78 - (void)_warmInitialProcess WK_API_AVAILABLE(macos(10.12), ios(10.0)); 77 79 - (void)_automationCapabilitiesDidChange WK_API_AVAILABLE(macos(10.12), ios(10.0)); -
branches/safari-612-branch/Source/WebKit/UIProcess/Cocoa/NavigationState.mm
r278315 r282229 1061 1061 case ProcessTerminationReason::RequestedByClient: 1062 1062 return _WKProcessTerminationReasonRequestedByClient; 1063 case ProcessTerminationReason::ExceededProcessCountLimit: 1063 1064 case ProcessTerminationReason::RequestedByNetworkProcess: 1064 1065 case ProcessTerminationReason::RequestedByGPUProcess: -
branches/safari-612-branch/Source/WebKit/UIProcess/WebPageProxy.cpp
r281904 r282229 1413 1413 navigation.setIsLoadedWithNavigationShared(true); 1414 1414 1415 process->markProcessAsRecentlyUsed(); 1416 1415 1417 if (!process->isLaunching() || !url.isLocalFile()) 1416 1418 process->send(Messages::WebPage::LoadRequest(loadParameters), webPageID); … … 1474 1476 addPlatformLoadParameters(m_process, loadParameters); 1475 1477 1478 m_process->markProcessAsRecentlyUsed(); 1476 1479 if (m_process->isLaunching()) 1477 1480 send(Messages::WebPage::LoadRequestWaitingForProcessLaunch(loadParameters, resourceDirectoryURL, m_identifier, checkAssumedReadAccessToResourceURL)); … … 1533 1536 addPlatformLoadParameters(process, loadParameters); 1534 1537 1538 process->markProcessAsRecentlyUsed(); 1535 1539 process->assumeReadAccessToBaseURL(*this, baseURL); 1536 1540 process->send(Messages::WebPage::LoadData(loadParameters), webPageID); … … 1590 1594 addPlatformLoadParameters(m_process, loadParameters); 1591 1595 1596 m_process->markProcessAsRecentlyUsed(); 1592 1597 m_process->assumeReadAccessToBaseURL(*this, baseURL); 1593 1598 m_process->send(Messages::WebPage::LoadSimulatedRequestAndResponse(loadParameters, simulatedResponse), m_webPageID); … … 1633 1638 addPlatformLoadParameters(process(), loadParameters); 1634 1639 1640 m_process->markProcessAsRecentlyUsed(); 1635 1641 m_process->assumeReadAccessToBaseURL(*this, baseURL.string()); 1636 1642 m_process->assumeReadAccessToBaseURL(*this, unreachableURL.string()); … … 1662 1668 addPlatformLoadParameters(process(), loadParameters); 1663 1669 1670 m_process->markProcessAsRecentlyUsed(); 1664 1671 send(Messages::WebPage::LoadData(loadParameters)); 1665 1672 m_process->startResponsivenessTimer(); … … 1737 1744 navigation->setUserContentExtensionsEnabled(false); 1738 1745 1746 m_process->markProcessAsRecentlyUsed(); 1739 1747 send(Messages::WebPage::Reload(navigation->navigationID(), options.toRaw(), sandboxExtensionHandle)); 1740 1748 m_process->startResponsivenessTimer(); … … 1815 1823 m_pageLoadState.setPendingAPIRequest(transaction, { navigation ? navigation->navigationID() : 0, item.url() }); 1816 1824 1825 m_process->markProcessAsRecentlyUsed(); 1817 1826 send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, std::nullopt, m_lastNavigationWasAppInitiated)); 1818 1827 m_process->startResponsivenessTimer(); … … 5173 5182 void WebPageProxy::viewIsBecomingVisible() 5174 5183 { 5184 m_process->markProcessAsRecentlyUsed(); 5175 5185 #if ENABLE(MEDIA_STREAM) 5176 5186 if (m_userMediaPermissionRequestManager) … … 7711 7721 case ProcessTerminationReason::Crash: 7712 7722 return true; 7723 case ProcessTerminationReason::ExceededProcessCountLimit: 7713 7724 case ProcessTerminationReason::NavigationSwap: 7714 7725 case ProcessTerminationReason::RequestedByClient: -
branches/safari-612-branch/Source/WebKit/UIProcess/WebProcessPool.cpp
r281032 r282229 867 867 return; 868 868 869 if (WebProcessProxy::hasReachedProcessCountLimit()) 870 return; 871 869 872 WEBPROCESSPOOL_RELEASE_LOG(PerformanceLogging, "prewarmProcess: Prewarming a WebProcess for performance"); 870 873 createNewWebProcess(nullptr, WebProcessProxy::IsPrewarmed::Yes); -
branches/safari-612-branch/Source/WebKit/UIProcess/WebProcessProxy.cpp
r281007 r282229 109 109 using namespace WebCore; 110 110 111 static unsigned s_maxProcessCount { 400 }; 112 113 static ListHashSet<WebProcessProxy*>& liveProcessesLRU() 114 { 115 ASSERT(RunLoop::isMain()); 116 static NeverDestroyed<ListHashSet<WebProcessProxy*>> processes; 117 return processes; 118 } 119 120 void WebProcessProxy::setProcessCountLimit(unsigned limit) 121 { 122 s_maxProcessCount = limit; 123 } 124 125 bool WebProcessProxy::hasReachedProcessCountLimit() 126 { 127 return liveProcessesLRU().size() >= s_maxProcessCount; 128 } 129 111 130 static bool isMainThreadOrCheckDisabled() 112 131 { … … 151 170 { 152 171 auto proxy = adoptRef(*new WebProcessProxy(processPool, websiteDataStore, isPrewarmed)); 153 if (shouldLaunchProcess == ShouldLaunchProcess::Yes) 172 if (shouldLaunchProcess == ShouldLaunchProcess::Yes) { 173 if (liveProcessesLRU().size() >= s_maxProcessCount) { 174 for (auto& processPool : WebProcessPool::allProcessPools()) 175 processPool->webProcessCache().clear(); 176 if (liveProcessesLRU().size() >= s_maxProcessCount) 177 liveProcessesLRU().first()->requestTermination(ProcessTerminationReason::ExceededProcessCountLimit); 178 } 179 ASSERT(liveProcessesLRU().size() < s_maxProcessCount); 180 liveProcessesLRU().add(proxy.ptr()); 154 181 proxy->connect(); 182 } 155 183 return proxy; 156 184 } … … 237 265 WEBPROCESSPROXY_RELEASE_LOG(Process, "destructor:"); 238 266 267 liveProcessesLRU().remove(this); 268 239 269 for (auto identifier : m_speechRecognitionServerMap.keys()) 240 270 removeMessageReceiver(Messages::SpeechRecognitionServer::messageReceiverName(), identifier); … … 337 367 ASSERT(!m_isInProcessCache); 338 368 ASSERT(!m_provisionalPages.contains(&provisionalPage)); 369 markProcessAsRecentlyUsed(); 339 370 m_provisionalPages.add(&provisionalPage); 340 371 updateRegistrationWithDataStore(); … … 558 589 } 559 590 591 markProcessAsRecentlyUsed(); 560 592 m_pageMap.set(webPage.identifier(), &webPage); 561 593 globalPageMap().set(webPage.identifier(), &webPage); … … 888 920 // to be deleted before we can finish our work. 889 921 auto protectedThis = makeRef(*this); 922 923 liveProcessesLRU().remove(this); 890 924 891 925 #if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM) … … 1851 1885 { 1852 1886 WEBPROCESSPROXY_RELEASE_LOG(Loading, "establishServiceWorkerContext: Started"); 1887 markProcessAsRecentlyUsed(); 1853 1888 sendWithAsyncReply(Messages::WebProcess::EstablishWorkerContextConnectionToNetworkProcess { processPool().defaultPageGroup().pageGroupID(), m_serviceWorkerInformation->serviceWorkerPageProxyID, m_serviceWorkerInformation->serviceWorkerPageID, store, *m_registrableDomain, m_serviceWorkerInformation->initializationData }, [this, weakThis = makeWeakPtr(*this), completionHandler = WTFMove(completionHandler)]() mutable { 1854 1889 if (weakThis) … … 2001 2036 } 2002 2037 2038 void WebProcessProxy::markProcessAsRecentlyUsed() 2039 { 2040 if (liveProcessesLRU().contains(this)) 2041 liveProcessesLRU().appendOrMoveToLast(this); 2042 } 2043 2003 2044 void WebProcessProxy::systemBeep() 2004 2045 { -
branches/safari-612-branch/Source/WebKit/UIProcess/WebProcessProxy.h
r280451 r282229 165 165 PAL::SessionID sessionID() const; 166 166 167 static bool hasReachedProcessCountLimit(); 168 static void setProcessCountLimit(unsigned); 169 167 170 static WebProcessProxy* processForIdentifier(WebCore::ProcessIdentifier); 168 171 static WebPageProxy* webPage(WebPageProxyIdentifier); … … 409 412 #endif 410 413 414 void markProcessAsRecentlyUsed(); 415 411 416 #if PLATFORM(MAC) 412 417 void platformSuspendProcess(); -
branches/safari-612-branch/Tools/ChangeLog
r282152 r282229 1 2021-09-09 Russell Epstein <repstein@apple.com> 2 3 Cherry-pick r282218. rdar://problem/82931375 4 5 Implement a WebProcess cap 6 https://bugs.webkit.org/show_bug.cgi?id=230067 7 <rdar://79479244> 8 9 Reviewed by Geoffrey Garen. 10 11 Source/WebKit: 12 13 Implement a WebProcess cap to avoid getting into a state where we run out of resources and crash in various ways. 14 The current limit is 400 and can be changed via an SPI. The limit is per UIProcess (not per process pool). 15 When we try and launch a new WebProcess and the limit has been reached, we terminate the least recently used 16 WebProcess to avoid going over the limit. 17 18 * Shared/ProcessTerminationReason.h: 19 * UIProcess/API/C/WKAPICast.h: 20 (WebKit::toAPI): 21 * UIProcess/API/Cocoa/WKProcessPool.mm: 22 (+[WKProcessPool _setWebProcessCountLimit:]): 23 * UIProcess/API/Cocoa/WKProcessPoolPrivate.h: 24 * UIProcess/Cocoa/NavigationState.mm: 25 (WebKit::wkProcessTerminationReason): 26 * UIProcess/WebPageProxy.cpp: 27 (WebKit::WebPageProxy::loadRequestWithNavigationShared): 28 (WebKit::WebPageProxy::loadFile): 29 (WebKit::WebPageProxy::loadDataWithNavigationShared): 30 (WebKit::WebPageProxy::loadSimulatedRequest): 31 (WebKit::WebPageProxy::loadAlternateHTML): 32 (WebKit::WebPageProxy::loadWebArchiveData): 33 (WebKit::WebPageProxy::reload): 34 (WebKit::WebPageProxy::goToBackForwardItem): 35 (WebKit::shouldReloadAfterProcessTermination): 36 * UIProcess/WebProcessProxy.cpp: 37 (WebKit::WebProcessProxy::setProcessCountLimit): 38 (WebKit::WebProcessProxy::create): 39 (WebKit::WebProcessProxy::~WebProcessProxy): 40 (WebKit::WebProcessProxy::addProvisionalPageProxy): 41 (WebKit::WebProcessProxy::addExistingWebPage): 42 (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch): 43 (WebKit::WebProcessProxy::establishServiceWorkerContext): 44 (WebKit::WebProcessProxy::markProcessAsRecentlyUsed): 45 * UIProcess/WebProcessProxy.h: 46 47 Tools: 48 49 Add API test coverage. 50 51 * TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm: 52 (TEST): 53 54 git-svn-id: https://svn.webkit.org/repository/webkit/trunk@282218 268f45cc-cd09-0410-ab3c-d52691b4dbfc 55 56 2021-09-09 Chris Dumez <cdumez@apple.com> 57 58 Implement a WebProcess cap 59 https://bugs.webkit.org/show_bug.cgi?id=230067 60 <rdar://79479244> 61 62 Reviewed by Geoffrey Garen. 63 64 Add API test coverage. 65 66 * TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm: 67 (TEST): 68 1 69 2021-09-08 Alan Coon <alancoon@apple.com> 2 70 -
branches/safari-612-branch/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebContentProcessDidTerminate.mm
r273997 r282229 377 377 TestWebKitAPI::Util::run(&done); 378 378 } 379 380 TEST(WKNavigation, WebProcessLimit) 381 { 382 constexpr unsigned maxProcessCount = 10; 383 [WKProcessPool _setWebProcessCountLimit:maxProcessCount]; 384 385 auto navigationDelegate = adoptNS([[TestNavigationDelegate alloc] init]); 386 [navigationDelegate setDidFinishNavigation:^(WKWebView *, WKNavigation *) { 387 finishedLoad = true; 388 }]; 389 auto createWebView = [&] { 390 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 391 auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) configuration:configuration.get()]); 392 [webView setNavigationDelegate:navigationDelegate.get()]; 393 finishedLoad = false; 394 [webView loadTestPageNamed:@"simple"]; 395 TestWebKitAPI::Util::run(&finishedLoad); 396 return webView; 397 }; 398 399 [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView *) { 400 didCrash = true; 401 }]; 402 403 Vector<RetainPtr<WKWebView>> views; 404 for (unsigned i = 0; i < maxProcessCount; ++i) 405 views.append(createWebView()); 406 EXPECT_FALSE(didCrash); 407 for (auto& view : views) 408 EXPECT_NE([view _webProcessIdentifier], 0); 409 410 // We have now reached the WebProcess cap, let's try and launch a new one. 411 __block unsigned crashCount = 0; 412 [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView * view) { 413 EXPECT_EQ(views[0], view); 414 ++crashCount; 415 }]; 416 views.append(createWebView()); 417 418 EXPECT_EQ(crashCount, 1U); 419 for (unsigned i = 0; i < views.size(); ++i) { 420 if (!i) 421 EXPECT_EQ([views[i] _webProcessIdentifier], 0); 422 else 423 EXPECT_NE([views[i] _webProcessIdentifier], 0); 424 } 425 426 crashCount = 0; 427 [navigationDelegate setWebContentProcessDidTerminate:^(WKWebView * view) { 428 EXPECT_EQ(views[1], view); 429 ++crashCount; 430 }]; 431 views.append(createWebView()); 432 433 EXPECT_EQ(crashCount, 1U); 434 for (unsigned i = 0; i < views.size(); ++i) { 435 if (i < 2) 436 EXPECT_EQ([views[i] _webProcessIdentifier], 0); 437 else 438 EXPECT_NE([views[i] _webProcessIdentifier], 0); 439 } 440 441 [WKProcessPool _setWebProcessCountLimit:400]; 442 }
Note:
See TracChangeset
for help on using the changeset viewer.