Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: e319714bc5284c981fcd26470d5537f4b39e1658
https://github.com/WebKit/WebKit/commit/e319714bc5284c981fcd26470d5537f4b39e1658
Author: Chris Dumez <[email protected]>
Date: 2026-06-09 (Tue, 09 Jun 2026)
Changed paths:
M Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp
Log Message:
-----------
WebSWClientConnection leaks pending callbacks when the network process
connection is lost
https://bugs.webkit.org/show_bug.cgi?id=316631
Reviewed by Youenn Fablet.
WebSWClientConnection::clear() — invoked from connectionToServerLost()
on network-process death and from the destructor — only called the base
class clearPendingJobs() and never drained the two per-instance queues
holding pending callbacks:
1. m_retrieveRecordResponseBodyCallbacks (HashMap of streaming
BackgroundFetch record-body callbacks). retrieveRecordResponseBody()
sends a fire-and-forget IPC and the callbacks fire only from the
notifyRecordResponseBodyChunk / notifyRecordResponseBodyEnd replies.
With the network process gone, the replies never arrive and each
in-flight body retrieval was silently dropped, leaving the
FetchResponse body / ReadableStream consumer on the JS side pending
forever. WorkerSWClientConnection::contextStopped() already handles
the equivalent case correctly (WorkerSWClientConnection.cpp:120-122).
2. m_tasksPendingOriginImport (Deque of tasks awaiting
setSWOriginTableIsImported()). With the connection closed,
setSWOriginTableIsImported() will never run, so the queue was only
emptied via the eventual destruction of the WebSWClientConnection.
getRegistrations() captured a plain CompletionHandler in the queued
task — destroying it unfired hit the
ASSERT_WITH_MESSAGE(!m_function, "Completion handler should always
be called") in debug and left the JS getRegistrations() promise hung
in release.
Fix clear() to drain both queues. Body callbacks are invoked with an
errorDomainWebKitInternal ResourceError. The pending-import tasks are
cleared by destruction; matchRegistration() already wrapped its callback
in a CompletionHandlerWithFinalizer that supplies std::nullopt on
destruction, so the destructor chain fires the JS-visible callback.
Apply the same wrapping to getRegistrations() (finalizer supplies an
empty Vector) so its destruction is also safe and observable.
std::exchange the body-callback map onto the stack before iterating to
avoid reentrant-mutation hazards.
* Source/WebKit/WebProcess/Storage/WebSWClientConnection.cpp:
(WebKit::WebSWClientConnection::getRegistrations):
Wrap the GetRegistrationsCallback in CompletionHandlerWithFinalizer with
an empty-Vector finalizer, mirroring matchRegistration().
(WebKit::WebSWClientConnection::clear):
Drain m_retrieveRecordResponseBodyCallbacks with a "Connection to
network process lost" ResourceError, and clear m_tasksPendingOriginImport
so each queued task's CompletionHandlerWithFinalizer destructor resolves
the corresponding JS promise with a default value.
Canonical link: https://commits.webkit.org/314859@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications