Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 03efc9761a39b4849f8c849c455b4f6806c250f9
https://github.com/WebKit/WebKit/commit/03efc9761a39b4849f8c849c455b4f6806c250f9
Author: Sihui Liu <[email protected]>
Date: 2026-08-26 (Wed, 26 Aug 2026)
Changed paths:
M Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.cpp
M Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.h
M Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
M Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
M Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp
M Tools/TestWebKitAPI/Tests/WebKit/WKWebView/IndexedDBSuspendImminently.mm
Log Message:
-----------
REGRESSION(315609@main): Stack overflow in NetworkProcess aborting the queued
transactions of a suspended process
https://bugs.webkit.org/show_bug.cgi?id=322386
rdar://184669941
Reviewed by Chris Dumez.
A page that queues many read-write transactions operating on the same object
store and is then suspended crashed the
network process. The cause is that handleTransactions() ended every scheduling
pass by calling
abortInProgressTransactionsBlockedOnSuspendedClients(), and that pass ended by
calling handleTransactions() again. When
the scopes all overlap, takeNextRunnableTransaction() starts exactly one
transaction before deferring the rest, so each
cycle handled a single queued transaction and cost one frame pair; the reported
crash recursed over 3000 levels.
Batching the aborts in 318222@main did not help, because there is never more
than one transaction to abort per pass.
This patch breaks the cycle at both ends. handleTransactions() no longer calls
the abort pass, and
takeNextRunnableTransaction() no longer picks transactions of suspended
clients: such a client cannot send requests, so
starting its transaction only holds the scope without making progress, and
since the SQLite backing stores serialize
writes it blocks every other client's writes as well.
The abort pass now runs only from the three points where the blocked set can
change, each followed by
handleTransactions() to start whatever became runnable:
- Suspending a client marks it suspended and aborts its in-progress
transactions that block an active client.
- Resuming a client marks it active and aborts the in-progress transactions of
still-suspended clients that now block
it.
- Queuing a transaction aborts the in-progress transactions of suspended
clients that block it.
All three are IPC entry points, so the abort pass is unreachable from the
scheduler and the recursion is structurally
impossible; a debug-only re-entrancy assertion replaces the recursion-depth
counter from 318222@main. A suspended
client's queued transactions are now kept rather than started and rolled back,
so their writes are no longer lost.
Also renamed setClientProcessSuspended() to setClientSuspended(), since a
client connection in this layer is already
identified by a ProcessIdentifier.
Added 3 IndexedDB API tests to expand coverage:
- ManyQueuedTransactionsOfSuspendedProcessAreDeferredNotAborted covers the
reported crash and checks that only the
in-progress transaction is aborted, that the 99 queued ones complete after
resume, and that the network process
survived.
- TransactionOfSuspendedProcessIsNotAbortedByItsOwnQueuedTransaction checks
that a suspended client's in-progress
transaction is left alone when the only thing waiting on it is that client's
own queued transaction.
- TransactionOfSuspendedProcessIsAbortedWhenAnotherSuspendedProcessResumes
checks that with two suspended clients,
resuming one aborts the other's in-progress transaction and starts the resumed
client's.
* Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.cpp:
(WebCore::IDBServer::IDBConnectionToClient::setClientSuspended):
(WebCore::IDBServer::IDBConnectionToClient::setClientProcessSuspended): Deleted.
* Source/WebCore/Modules/indexeddb/server/IDBConnectionToClient.h:
(WebCore::IDBServer::IDBConnectionToClient::isClientSuspended const):
(WebCore::IDBServer::IDBConnectionToClient::isClientProcessSuspended const):
Deleted.
* Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp:
(WebCore::IDBServer::UniqueIDBDatabase::enqueueTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::handleTransactions):
(WebCore::IDBServer::isTransactionOfSuspendedClient):
(WebCore::IDBServer::UniqueIDBDatabase::takeNextRunnableTransaction):
(WebCore::IDBServer::UniqueIDBDatabase::transactionBlocksPendingTransactions):
(WebCore::IDBServer::UniqueIDBDatabase::handleTransactionsAfterAbortingSuspendedClientTransactions):
(WebCore::IDBServer::UniqueIDBDatabase::abortInProgressTransactionsOfSuspendedClientsIfNeeded):
(WebCore::IDBServer::UniqueIDBDatabase::abortInProgressTransactionsBlockedOnSuspendedClients):
Deleted.
* Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h:
* Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp:
(WebKit::NetworkStorageManager::setWebProcessSuspended):
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/IndexedDBSuspendImminently.mm:
(ManyQueuedTransactionsOfSuspendedProcessAreDeferredNotAborted)):
(TransactionOfSuspendedProcessIsNotAbortedByItsOwnQueuedTransaction)):
(TransactionOfSuspendedProcessIsAbortedWhenAnotherSuspendedProcessResumes)):
Canonical link: https://commits.webkit.org/319873@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications