Bug 222011

Summary: REGRESSION(r268097): Calling processDidTerminate delegate asynchronously is risky compatibility-wise
Product: WebKit Reporter: Chris Dumez <cdumez>
Component: WebKit2Assignee: Chris Dumez <cdumez>
Status: RESOLVED FIXED    
Severity: Normal CC: achristensen, beidson, cgarcia, darin, ggaren, luming_yin, mcatanzaro, thorton, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
See Also: https://bugs.webkit.org/show_bug.cgi?id=222809
Bug Depends on:    
Bug Blocks: 217407    
Attachments:
Description Flags
Patch none

Chris Dumez
Reported 2021-02-16 17:32:52 PST
Calling processDidTerminate delegate asynchronously like we did in r268097 is risky compatibility-wise. This caused breakage in at least 2 client applications. While this can be dealt with on the client side, it would be better to fix what r268097 was trying to fix without making the delegate call asynchronous. The reason calling the delegate asynchronously is risky is because some view state may have time to get reset by the time the client gets notified on the crash, potentially confusing the crash handling logic in the client.
Attachments
Patch (7.21 KB, patch)
2021-02-16 17:36 PST, Chris Dumez
no flags
Chris Dumez
Comment 1 2021-02-16 17:36:02 PST
Luming Yin
Comment 2 2021-02-16 21:08:53 PST
Carlos Garcia Campos
Comment 3 2021-02-17 01:08:40 PST
Comment on attachment 420567 [details] Patch Thanks!
EWS
Comment 4 2021-02-17 01:14:12 PST
commit-queue failed to commit attachment 420567 [details] to WebKit repository. To retry, please set cq+ flag again.
EWS
Comment 5 2021-02-17 01:38:53 PST
Committed r272990: <https://commits.webkit.org/r272990> All reviewed patches have been landed. Closing bug and clearing flags on attachment 420567 [details].
Michael Catanzaro
Comment 6 2021-03-05 09:12:40 PST
Hi Chris, it looks like this didn't actually fix Epiphany. The problem is here in WebProcessProxy::processDidTerminateOrFailedToLaunch: for (auto& page : pages) page->resetStateAfterProcessTermination(reason); for (auto& provisionalPage : provisionalPages) { if (provisionalPage) provisionalPage->processDidTerminate(); } for (auto& page : pages) page->dispatchProcessDidTerminate(reason); WebPageProxy::resetStateAfterProcessTermination calls WebPageProxy::resetStateAfterProcessExited, which resets its m_pageLoadState, here: if (terminationReason != ProcessTerminationReason::NavigationSwap) { PageLoadState::Transaction transaction = m_pageLoadState.transaction(); m_pageLoadState.reset(transaction); } That clears the page's URI, and as you see above it happens just before WebProcessProxy calls WebPageProxy::dispatchProcessDidTerminate. To avoid this regression, we would need to ensure the page's URI doesn't get reset until *after* WebPageProxy::dispatchProcessDidTerminate. Again, easy to workaround in the client, but would be nice if we didn't need to. How bad would it be to move the code that resets the PageLoadState to a later point?
Chris Dumez
Comment 7 2021-03-05 09:16:44 PST
(In reply to Michael Catanzaro from comment #6) > Hi Chris, it looks like this didn't actually fix Epiphany. The problem is > here in WebProcessProxy::processDidTerminateOrFailedToLaunch: > > for (auto& page : pages) > page->resetStateAfterProcessTermination(reason); > > for (auto& provisionalPage : provisionalPages) { > if (provisionalPage) > provisionalPage->processDidTerminate(); > } > > for (auto& page : pages) > page->dispatchProcessDidTerminate(reason); > > WebPageProxy::resetStateAfterProcessTermination calls > WebPageProxy::resetStateAfterProcessExited, which resets its > m_pageLoadState, here: > > if (terminationReason != ProcessTerminationReason::NavigationSwap) { > PageLoadState::Transaction transaction = > m_pageLoadState.transaction(); > m_pageLoadState.reset(transaction); > } > > That clears the page's URI, and as you see above it happens just before > WebProcessProxy calls WebPageProxy::dispatchProcessDidTerminate. To avoid > this regression, we would need to ensure the page's URI doesn't get reset > until *after* WebPageProxy::dispatchProcessDidTerminate. > > Again, easy to workaround in the client, but would be nice if we didn't need > to. How bad would it be to move the code that resets the PageLoadState to a > later point? I don't understand why this is a regression from my original change then though. We always called resetStateAfterProcessExited() *before* notifying the client.
Chris Dumez
Comment 8 2021-03-05 10:20:59 PST
(In reply to Chris Dumez from comment #7) > (In reply to Michael Catanzaro from comment #6) > > Hi Chris, it looks like this didn't actually fix Epiphany. The problem is > > here in WebProcessProxy::processDidTerminateOrFailedToLaunch: > > > > for (auto& page : pages) > > page->resetStateAfterProcessTermination(reason); > > > > for (auto& provisionalPage : provisionalPages) { > > if (provisionalPage) > > provisionalPage->processDidTerminate(); > > } > > > > for (auto& page : pages) > > page->dispatchProcessDidTerminate(reason); > > > > WebPageProxy::resetStateAfterProcessTermination calls > > WebPageProxy::resetStateAfterProcessExited, which resets its > > m_pageLoadState, here: > > > > if (terminationReason != ProcessTerminationReason::NavigationSwap) { > > PageLoadState::Transaction transaction = > > m_pageLoadState.transaction(); > > m_pageLoadState.reset(transaction); > > } > > > > That clears the page's URI, and as you see above it happens just before > > WebProcessProxy calls WebPageProxy::dispatchProcessDidTerminate. To avoid > > this regression, we would need to ensure the page's URI doesn't get reset > > until *after* WebPageProxy::dispatchProcessDidTerminate. > > > > Again, easy to workaround in the client, but would be nice if we didn't need > > to. How bad would it be to move the code that resets the PageLoadState to a > > later point? > > I don't understand why this is a regression from my original change then > though. We always called resetStateAfterProcessExited() *before* notifying > the client. Oh, I think it is because there was this in scope: PageLoadState::Transaction transaction = m_pageLoadState.transaction(); So even though we cleared the URL before call the client, the change would not take effect until after the transaction gets destroyed, which was *after* we called the client.. So it seems I indeed changed behavior here :/
Michael Catanzaro
Comment 9 2021-03-05 10:56:19 PST
Chris posted a fix in bug #222809.
Note You need to log in before you can comment on or make changes to this bug.