Changeset 284786 in webkit
- Timestamp:
- Oct 25, 2021, 8:37:16 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 18 edited
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp (modified) (2 diffs)
-
Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h (modified) (2 diffs)
-
Source/WebKit/GPUProcess/GPUProcess.cpp (modified) (1 diff)
-
Source/WebKit/GPUProcess/GPUProcess.h (modified) (1 diff)
-
Source/WebKit/GPUProcess/GPUProcess.messages.in (modified) (1 diff)
-
Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp (modified) (4 diffs)
-
Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.h (modified) (1 diff)
-
Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp (modified) (2 diffs)
-
Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h (modified) (1 diff)
-
Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm (modified) (2 diffs)
-
Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp (modified) (1 diff)
-
Source/WebKit/UIProcess/GPU/GPUProcessProxy.h (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (modified) (4 diffs)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/canvas-image-data.html (added)
-
Tools/TestWebKitAPI/cocoa/TestWKWebView.h (modified) (1 diff)
-
Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r284775 r284786 1 2021-10-25 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 REGRESSION (r284079): Audio continues playing on hulu.com in private browsing mode after closing the tab 4 https://bugs.webkit.org/show_bug.cgi?id=232113 5 rdar://84399283 6 7 Reviewed by Chris Dumez. 8 9 I inadvertently introduced a ref-counting cycle between RemoteRenderingBackend and RemoteDisplayListRecorder 10 after IPC stream refactoring in r284079, since RemoteDisplayListRecorder directly strongly refs the rendering 11 backend, and the rendering backend indirectly holds on to RemoteDisplayListRecorders through remote image 12 buffers in the resource cache. Since RemoteRenderingBackend also strongly refs GPUConnectionToWebProcess as 13 well, this caused the entire GPUConnectionToWebProcess to leak after tearing down the connected web process, if 14 the web process ever installed a remote rendering backend for 2D canvas. 15 16 To avoid this cycle, turn RemoteDisplayListRecorder's `m_renderingBackend` into a RefPtr instead of a Ref, and 17 clear it out in `stopListeningForIPC()`. This also means that we no longer need a separate boolean flag to 18 ensure that `RemoteDisplayListRecorder::stopListeningForIPC()` is idempotent, so we also remove 19 `m_isListeningForIPC` altogether. 20 21 Test: GPUProcess.DoNotLeakConnectionAfterClosingWebPage 22 23 * GPUProcess/GPUConnectionToWebProcess.cpp: 24 (WebKit::GPUConnectionToWebProcess::GPUConnectionToWebProcess): 25 (WebKit::GPUConnectionToWebProcess::~GPUConnectionToWebProcess): 26 * GPUProcess/GPUConnectionToWebProcess.h: 27 (WebKit::GPUConnectionToWebProcess::objectCountForTesting): 28 * GPUProcess/GPUProcess.cpp: 29 (WebKit::GPUProcess::webProcessConnectionCountForTesting): 30 31 Add support for a testing-only SPI hook to ask for the live GPUConnectionToWebProcess count. This retrieves a 32 statically incremented/decremented count of the GPUConnectionToWebProcess instances that exist in the GPU 33 process; importantly, this is different from asking the GPUProcess for the number of connections in 34 `m_webProcessConnections`, since the latter will be 0 even when one or more GPUConnectionToWebProcesses are 35 still alive. 36 37 * GPUProcess/GPUProcess.h: 38 * GPUProcess/GPUProcess.messages.in: 39 * GPUProcess/graphics/RemoteDisplayListRecorder.cpp: 40 (WebKit::RemoteDisplayListRecorder::RemoteDisplayListRecorder): 41 42 Also fix a leak caused by RemoteDisplayListRecorder and RemoteImageBuffer strongly reffing each other. Since 43 RemoteImageBuffer owns RemoteDisplayListRecorder, the backpointer from RemoteDisplayListRecorder to the image 44 buffer should be weak, not strong. 45 46 (WebKit::RemoteDisplayListRecorder::startListeningForIPC): 47 (WebKit::RemoteDisplayListRecorder::stopListeningForIPC): 48 (WebKit::RemoteDisplayListRecorder::paintFrameForMedia): 49 * GPUProcess/graphics/RemoteDisplayListRecorder.h: 50 (): Deleted. 51 * GPUProcess/graphics/RemoteRenderingBackend.cpp: 52 (WebKit::RemoteRenderingBackend::stopListeningForIPC): 53 54 Adjust this logic to ensure that we finish pending work and destroy cached resources *right before* we stop 55 listening for all stream IPC messages. Since RemoteDisplayListRecorder now clears out its pointer to the 56 rendering backend in `stopListeningForIPC()`, we'll need to ensure that any pending IPC stream messages that 57 might cause RemoteDisplayListRecorder to call into the back end are processed before we sever the IPC stream 58 connection for good by removing all receivers. 59 60 * UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h: 61 62 Add the new testing SPI (see above for more details). 63 64 * UIProcess/API/Cocoa/WKWebViewTesting.mm: 65 (-[WKWebView _gpuToWebProcessConnectionCountForTesting:]): 66 * UIProcess/GPU/GPUProcessProxy.cpp: 67 (WebKit::GPUProcessProxy::webProcessConnectionCountForTesting): 68 * UIProcess/GPU/GPUProcessProxy.h: 69 1 70 2021-10-25 Sam Sneddon <gsnedders@apple.com> 2 71 -
trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp
r284220 r284786 249 249 m_connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true); 250 250 m_connection->open(); 251 252 ++gObjectCountForTesting; 251 253 } 252 254 … … 263 265 m_libWebRTCCodecsProxy->close(); 264 266 #endif 265 } 267 268 --gObjectCountForTesting; 269 } 270 271 uint64_t GPUConnectionToWebProcess::gObjectCountForTesting = 0; 266 272 267 273 void GPUConnectionToWebProcess::didClose(IPC::Connection& connection) -
trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h
r284220 r284786 171 171 #endif 172 172 173 static uint64_t objectCountForTesting() { return gObjectCountForTesting; } 174 173 175 using RemoteRenderingBackendMap = HashMap<RenderingBackendIdentifier, IPC::ScopedActiveMessageReceiveQueue<RemoteRenderingBackend>>; 174 176 const RemoteRenderingBackendMap& remoteRenderingBackendMap() const { return m_remoteRenderingBackendMap; } … … 243 245 #endif 244 246 247 static uint64_t gObjectCountForTesting; 248 245 249 RefPtr<Logger> m_logger; 246 250 -
trunk/Source/WebKit/GPUProcess/GPUProcess.cpp
r284135 r284786 499 499 #endif 500 500 501 void GPUProcess::webProcessConnectionCountForTesting(CompletionHandler<void(uint64_t)>&& completionHandler) 502 { 503 completionHandler(GPUConnectionToWebProcess::objectCountForTesting()); 504 } 505 501 506 } // namespace WebKit 502 507 -
trunk/Source/WebKit/GPUProcess/GPUProcess.h
r283116 r284786 101 101 const String& applicationVisibleName() const { return m_applicationVisibleName; } 102 102 103 void webProcessConnectionCountForTesting(CompletionHandler<void(uint64_t)>&&); 104 103 105 private: 104 106 void lowMemoryHandler(Critical, Synchronous); -
trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in
r283116 r284786 69 69 NotifyPreferencesChanged(String domain, String key, std::optional<String> encodedValue) 70 70 #endif 71 72 WebProcessConnectionCountForTesting() -> (uint64_t count) Async 71 73 } 72 74 -
trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp
r284695 r284786 38 38 , m_imageBufferIdentifier(imageBufferIdentifier) 39 39 , m_webProcessIdentifier(webProcessIdentifier) 40 , m_renderingBackend( renderingBackend)40 , m_renderingBackend(&renderingBackend) 41 41 { 42 42 } … … 54 54 void RemoteDisplayListRecorder::startListeningForIPC() 55 55 { 56 ASSERT(!m_isListeningForIPC);57 m_isListeningForIPC = true;58 56 m_renderingBackend->streamConnection().startReceivingMessages(*this, Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64()); 59 57 } … … 61 59 void RemoteDisplayListRecorder::stopListeningForIPC() 62 60 { 63 if (!m_isListeningForIPC) 64 return; 65 66 m_renderingBackend->streamConnection().stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64()); 67 m_isListeningForIPC = false; 61 if (auto renderingBackend = std::exchange(m_renderingBackend, { })) 62 renderingBackend->streamConnection().stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64()); 68 63 } 69 64 … … 427 422 void RemoteDisplayListRecorder::paintFrameForMedia(MediaPlayerIdentifier identifier, const FloatRect& destination) 428 423 { 429 m_renderingBackend->performWithMediaPlayerOnMainThread(identifier, [imageBuffer = m_imageBuffer.copyRef(), destination](MediaPlayer& player) {424 m_renderingBackend->performWithMediaPlayerOnMainThread(identifier, [imageBuffer = RefPtr { m_imageBuffer.get() }, destination](MediaPlayer& player) { 430 425 // It is currently not safe to call paintFrameForMedia() off the main thread. 431 426 imageBuffer->context().paintFrameForMedia(player, destination); -
trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.h
r283991 r284786 150 150 void didReceiveStreamMessage(IPC::StreamServerConnectionBase&, IPC::Decoder&) final; 151 151 152 Ref<WebCore::ImageBuffer> m_imageBuffer;152 WeakPtr<WebCore::ImageBuffer> m_imageBuffer; 153 153 QualifiedRenderingResourceIdentifier m_imageBufferIdentifier; 154 154 WebCore::ProcessIdentifier m_webProcessIdentifier; 155 Ref <RemoteRenderingBackend> m_renderingBackend;155 RefPtr<RemoteRenderingBackend> m_renderingBackend; 156 156 RefPtr<WebCore::ImageBuffer> m_maskImageBuffer; 157 bool m_isListeningForIPC { false };158 157 }; 159 158 -
trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp
r284768 r284786 109 109 { 110 110 ASSERT(RunLoop::isMain()); 111 // Make sure we destroy the ResourceCache on the WorkQueue since it gets populated on the WorkQueue. 112 // Make sure rendering resource request is released after destroying the cache. 113 m_workQueue->dispatch([renderingResourcesRequest = WTFMove(m_renderingResourcesRequest), remoteResourceCache = WTFMove(m_remoteResourceCache)] { }); 114 m_workQueue->stopAndWaitForCompletion(); 115 111 116 m_streamConnection->stopReceivingMessages(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64()); 112 117 m_streamConnection->stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName()); … … 118 123 remoteContext.value->stopListeningForIPC(); 119 124 } 120 121 // Make sure we destroy the ResourceCache on the WorkQueue since it gets populated on the WorkQueue.122 // Make sure rendering resource request is released after destroying the cache.123 m_workQueue->dispatch([renderingResourcesRequest = WTFMove(m_renderingResourcesRequest), remoteResourceCache = WTFMove(m_remoteResourceCache)] { });124 m_workQueue->stopAndWaitForCompletion();125 125 } 126 126 -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h
r284544 r284786 115 115 116 116 - (void)_createMediaSessionCoordinatorForTesting:(id <_WKMediaSessionCoordinator>)privateCoordinator completionHandler:(void(^)(BOOL))completionHandler; 117 - (void)_gpuToWebProcessConnectionCountForTesting:(void(^)(NSUInteger))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA)); 117 118 118 119 @end -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm
r284544 r284786 28 28 29 29 #import "AudioSessionRoutingArbitratorProxy.h" 30 #import "GPUProcessProxy.h" 30 31 #import "MediaSessionCoordinatorProxyPrivate.h" 31 32 #import "PlaybackSessionManagerProxy.h" … … 424 425 } 425 426 427 - (void)_gpuToWebProcessConnectionCountForTesting:(void(^)(NSUInteger))completionHandler 428 { 429 RefPtr gpuProcess = _page->process().processPool().gpuProcess(); 430 if (!gpuProcess) { 431 completionHandler(0); 432 return; 433 } 434 435 gpuProcess->webProcessConnectionCountForTesting([completionHandler = makeBlockPtr(completionHandler)](uint64_t count) { 436 completionHandler(count); 437 }); 438 } 439 426 440 - (void)_createMediaSessionCoordinatorForTesting:(id <_WKMediaSessionCoordinator>)privateCoordinator completionHandler:(void(^)(BOOL))completionHandler 427 441 { -
trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp
r284641 r284786 400 400 } 401 401 402 void GPUProcessProxy::webProcessConnectionCountForTesting(CompletionHandler<void(uint64_t)>&& completionHandler) 403 { 404 sendWithAsyncReply(Messages::GPUProcess::WebProcessConnectionCountForTesting(), WTFMove(completionHandler)); 405 } 406 402 407 void GPUProcessProxy::didClose(IPC::Connection&) 403 408 { -
trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h
r284641 r284786 95 95 96 96 void terminateForTesting(); 97 void webProcessConnectionCountForTesting(CompletionHandler<void(uint64_t)>&&); 97 98 98 99 private: -
trunk/Tools/ChangeLog
r284785 r284786 1 2021-10-25 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 REGRESSION (r284079): Audio continues playing on hulu.com in private browsing mode after closing the tab 4 https://bugs.webkit.org/show_bug.cgi?id=232113 5 rdar://84399283 6 7 Reviewed by Chris Dumez. 8 9 Add a new API test to verify that the GPU to web prcoess connection isn't leaked in the GPU process. See WebKit 10 ChangeLog for more details. 11 12 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: 13 * TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm: 14 * TestWebKitAPI/Tests/WebKitCocoa/canvas-image-data.html: Added. 15 * TestWebKitAPI/cocoa/TestWKWebView.h: 16 * TestWebKitAPI/cocoa/TestWKWebView.mm: 17 (-[WKWebView gpuToWebProcessConnectionCount]): 18 1 19 2021-10-25 Simon Fraser <simon.fraser@apple.com> 2 20 -
trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
r284748 r284786 1296 1296 F4E0A2B82122847400AF7C7F /* TestFilePromiseReceiver.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4E0A2B72122847400AF7C7F /* TestFilePromiseReceiver.mm */; }; 1297 1297 F4E3D80820F70BB9007B58C5 /* significant-text-milestone-article.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4E3D80720F708E4007B58C5 /* significant-text-milestone-article.html */; }; 1298 F4E7A66327222CA900E74D36 /* canvas-image-data.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4E7A66227222BB100E74D36 /* canvas-image-data.html */; }; 1298 1299 F4EB4E912328AC3000574DAB /* NSItemProviderAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4EB4E902328AC3000574DAB /* NSItemProviderAdditions.mm */; }; 1299 1300 F4EC8094260D30540010311D /* simple-image-overlay.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4EC8093260D2E620010311D /* simple-image-overlay.html */; }; … … 1445 1446 7C486BA11AA12567003F6F9B /* bundle-file.html in Copy Resources */, 1446 1447 26DF5A6315A2A27E003689C2 /* CancelLoadFromResourceLoadDelegate.html in Copy Resources */, 1448 F4E7A66327222CA900E74D36 /* canvas-image-data.html in Copy Resources */, 1447 1449 2EFF06C51D8867760004BB30 /* change-video-source-on-click.html in Copy Resources */, 1448 1450 2EFF06C71D886A580004BB30 /* change-video-source-on-end.html in Copy Resources */, … … 3188 3190 F4E0A2B72122847400AF7C7F /* TestFilePromiseReceiver.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TestFilePromiseReceiver.mm; sourceTree = "<group>"; }; 3189 3191 F4E3D80720F708E4007B58C5 /* significant-text-milestone-article.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "significant-text-milestone-article.html"; sourceTree = "<group>"; }; 3192 F4E7A66227222BB100E74D36 /* canvas-image-data.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "canvas-image-data.html"; sourceTree = "<group>"; }; 3190 3193 F4EB4E8F2328AC3000574DAB /* NSItemProviderAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSItemProviderAdditions.h; path = cocoa/NSItemProviderAdditions.h; sourceTree = SOURCE_ROOT; }; 3191 3194 F4EB4E902328AC3000574DAB /* NSItemProviderAdditions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = NSItemProviderAdditions.mm; path = cocoa/NSItemProviderAdditions.mm; sourceTree = SOURCE_ROOT; }; … … 4051 4054 464C764C230DF83200AFB020 /* BadServiceWorkerRegistrations-4.sqlite3 */, 4052 4055 2DE71AFF1D49C2F000904094 /* blinking-div.html */, 4056 F4E7A66227222BB100E74D36 /* canvas-image-data.html */, 4053 4057 2EFF06C41D8867700004BB30 /* change-video-source-on-click.html */, 4054 4058 2EFF06C61D886A560004BB30 /* change-video-source-on-end.html */, -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm
r280951 r284786 283 283 } 284 284 285 TEST(GPUProcess, DoNotLeakConnectionAfterClosingWebPage) 286 { 287 auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); 288 WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], true, WKStringCreateWithUTF8CString("UseGPUProcessForCanvasRenderingEnabled")); 289 WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], false, WKStringCreateWithUTF8CString("UseGPUProcessForDOMRenderingEnabled")); 290 291 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]); 292 [webView synchronouslyLoadTestPageNamed:@"canvas-image-data"]; 293 EXPECT_EQ(1U, [webView gpuToWebProcessConnectionCount]); 294 [webView _close]; 295 296 while ([webView gpuToWebProcessConnectionCount]) 297 TestWebKitAPI::Util::sleep(0.1); 298 } 299 285 300 #if ENABLE(LEGACY_ENCRYPTED_MEDIA) 286 301 TEST(GPUProcess, LegacyCDM) -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h
r284738 r284786 54 54 - (NSArray<_WKTextInputContext *> *)synchronouslyRequestTextInputContextsInRect:(CGRect)rect; 55 55 #endif 56 @property (nonatomic, readonly) NSUInteger gpuToWebProcessConnectionCount; 56 57 @property (nonatomic, readonly) NSString *contentsAsString; 57 58 @property (nonatomic, readonly) NSArray<NSString *> *tagsInBody; -
trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm
r284738 r284786 155 155 #endif // PLATFORM(IOS_FAMILY) 156 156 157 - (NSUInteger)gpuToWebProcessConnectionCount 158 { 159 __block bool done = false; 160 __block NSUInteger count = 0; 161 [self _gpuToWebProcessConnectionCountForTesting:^(NSUInteger result) { 162 done = true; 163 count = result; 164 }]; 165 TestWebKitAPI::Util::run(&done); 166 return count; 167 } 168 157 169 - (NSString *)contentsAsString 158 170 {
Note:
See TracChangeset
for help on using the changeset viewer.