Skip to content
Permalink
Browse files
IndexedDB: leak IDBDatabase and IDBTransacstion in layout tests
https://bugs.webkit.org/show_bug.cgi?id=194709

Reviewed by Geoffrey Garen.

Source/WebCore:

When connection to IDB server is closed, IDBTransaction would abort without notifying IDBDatabase, so
IDBDatabase didn't clear its reference to IDBTransaction which created a reference cycle.

Also IDBTransaction didn't clear its reference to IDBRequest in this case and it led to another reference cycle
between IDBOpenDBRequest and IDBTransaction.

Test: storage/indexeddb/IDBObject-leak.html

* Modules/indexeddb/IDBDatabase.cpp:
(WebCore::IDBDatabase::connectionToServerLost):
* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::IDBTransaction):
(WebCore::IDBTransaction::~IDBTransaction):
(WebCore::IDBTransaction::finishedDispatchEventForRequest):
(WebCore::IDBTransaction::connectionClosedFromServer):
* Modules/indexeddb/IDBTransaction.h:
* testing/Internals.cpp:
(WebCore::Internals::numberOfIDBTransactions const):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

* storage/indexeddb/IDBObject-leak.html: Added.


Canonical link: https://commits.webkit.org/209157@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@241722 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
szewai committed Feb 18, 2019
1 parent 5f1fdec commit 56e09166243ffa9145ab5a6607705628799b1c0a
Showing 9 changed files with 105 additions and 2 deletions.
@@ -1,3 +1,12 @@
2019-02-18 Sihui Liu <sihui_liu@apple.com>

IndexedDB: leak IDBDatabase and IDBTransacstion in layout tests
https://bugs.webkit.org/show_bug.cgi?id=194709

Reviewed by Geoffrey Garen.

* storage/indexeddb/IDBObject-leak.html: Added.

2019-02-18 Megan Gardner <megan_gardner@apple.com>

Turn On Smart Delete
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<script src="../../resources/js-test.js"></script>
<script src="resources/shared.js"></script>
<script>
description('This test verifies that IDBTransaction objects are freed.');

function test() {
if (!window.internals || !internals.numberOfIDBTransactions) {
testFailed('This test requires access to the Internals object');
finishJSTest();
return;
}

if (sessionStorage.doneFirstLoad) {
gc();
shouldBeEqualToNumber("internals.numberOfIDBTransactions()", 0);
finishJSTest();
return;
}

var dbname = setDBNameFromPath() + Date();
var request = window.indexedDB.open(dbname);
request.onupgradeneeded = function(evt) {
sessionStorage.doneFirstLoad = true;
if (window.testRunner) {
testRunner.waitUntilDone();
testRunner.terminateNetworkProcess();
} else {
testFailed('This test requires access to the TestRunner object');
}
setTimeout((()=> {
location.reload();
}), 0);
}
}

test();
</script>
@@ -1,3 +1,31 @@
2019-02-18 Sihui Liu <sihui_liu@apple.com>

IndexedDB: leak IDBDatabase and IDBTransacstion in layout tests
https://bugs.webkit.org/show_bug.cgi?id=194709

Reviewed by Geoffrey Garen.

When connection to IDB server is closed, IDBTransaction would abort without notifying IDBDatabase, so
IDBDatabase didn't clear its reference to IDBTransaction which created a reference cycle.

Also IDBTransaction didn't clear its reference to IDBRequest in this case and it led to another reference cycle
between IDBOpenDBRequest and IDBTransaction.

Test: storage/indexeddb/IDBObject-leak.html

* Modules/indexeddb/IDBDatabase.cpp:
(WebCore::IDBDatabase::connectionToServerLost):
* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::IDBTransaction):
(WebCore::IDBTransaction::~IDBTransaction):
(WebCore::IDBTransaction::finishedDispatchEventForRequest):
(WebCore::IDBTransaction::connectionClosedFromServer):
* Modules/indexeddb/IDBTransaction.h:
* testing/Internals.cpp:
(WebCore::Internals::numberOfIDBTransactions const):
* testing/Internals.h:
* testing/Internals.idl:

2019-02-18 Chris Fleizach <cfleizach@apple.com>

AX: PSON: Going back from apple.com to search results, cannot interact with HTML content. Disabling Swap Processes on Cross-Site Navigation resolves the issue.
@@ -264,7 +264,8 @@ void IDBDatabase::connectionToServerLost(const IDBError& error)
m_closePending = true;
m_closedInServer = true;

for (auto& transaction : m_activeTransactions.values())
auto transactions = copyToVector(m_activeTransactions.values());
for (auto& transaction : transactions)
transaction->connectionClosedFromServer(error);

auto errorEvent = Event::create(m_eventNames.errorEvent, Event::CanBubble::Yes, Event::IsCancelable::No);
@@ -79,6 +79,9 @@ IDBTransaction::IDBTransaction(IDBDatabase& database, const IDBTransactionInfo&
, m_currentlyCompletingRequest(request)

{
auto addResult = allIDBTransactions().add(this);
ASSERT_UNUSED(addResult, addResult.isNewEntry);

LOG(IndexedDB, "IDBTransaction::IDBTransaction - %s", m_info.loggingString().utf8().data());
ASSERT(&m_database->originThread() == &Thread::current());

@@ -106,6 +109,14 @@ IDBTransaction::IDBTransaction(IDBDatabase& database, const IDBTransactionInfo&
IDBTransaction::~IDBTransaction()
{
ASSERT(&m_database->originThread() == &Thread::current());
ASSERT(allIDBTransactions().contains(this));
allIDBTransactions().remove(this);
}

HashSet<IDBTransaction*>& IDBTransaction::allIDBTransactions()
{
static NeverDestroyed<HashSet<IDBTransaction*>> transactions;
return transactions;
}

IDBClient::IDBConnectionProxy& IDBTransaction::connectionProxy()
@@ -1434,7 +1445,8 @@ void IDBTransaction::connectionClosedFromServer(const IDBError& error)
{
LOG(IndexedDB, "IDBTransaction::connectionClosedFromServer - %s", error.message().utf8().data());

m_state = IndexedDB::TransactionState::Aborting;
m_database->willAbortTransaction(*this);
transitionedToFinishing(IndexedDB::TransactionState::Aborting);

abortInProgressOperations(error);

@@ -1445,6 +1457,7 @@ void IDBTransaction::connectionClosedFromServer(const IDBError& error)
ASSERT(m_transactionOperationsInProgressQueue.first() == operation.get());
operation->doComplete(IDBResultData::error(operation->identifier(), error));
}
m_currentlyCompletingRequest = nullptr;

connectionProxy().forgetActiveOperations(operations);

@@ -1454,6 +1467,7 @@ void IDBTransaction::connectionClosedFromServer(const IDBError& error)

m_idbError = error;
m_domError = error.toDOMException();
m_database->didAbortTransaction(*this);
fireOnAbort();
}

@@ -152,6 +152,8 @@ class IDBTransaction : public ThreadSafeRefCounted<IDBTransaction>, public Event

void visitReferencedObjectStores(JSC::SlotVisitor&) const;

WEBCORE_EXPORT static HashSet<IDBTransaction*>& allIDBTransactions();

private:
IDBTransaction(IDBDatabase&, const IDBTransactionInfo&, IDBOpenDBRequest*);

@@ -93,6 +93,8 @@
#include "HistoryController.h"
#include "HistoryItem.h"
#include "HitTestResult.h"
#include "IDBRequest.h"
#include "IDBTransaction.h"
#include "InspectorClient.h"
#include "InspectorController.h"
#include "InspectorFrontendClientLocal.h"
@@ -2383,6 +2385,11 @@ ExceptionOr<unsigned> Internals::countFindMatches(const String& text, const Vect
return document->page()->countFindMatches(text, parsedOptions.releaseReturnValue(), 1000);
}

unsigned Internals::numberOfIDBTransactions() const
{
return IDBTransaction::allIDBTransactions().size();
}

unsigned Internals::numberOfLiveNodes() const
{
unsigned nodeCount = 0;
@@ -378,6 +378,8 @@ class Internals final : public RefCounted<Internals>, private ContextDestruction
ExceptionOr<void> insertAuthorCSS(const String&) const;
ExceptionOr<void> insertUserCSS(const String&) const;

unsigned numberOfIDBTransactions() const;

unsigned numberOfLiveNodes() const;
unsigned numberOfLiveDocuments() const;
unsigned referencingNodeCount(const Document&) const;
@@ -405,6 +405,8 @@ enum CompositingPolicy {
void beginSimulatedMemoryPressure();
void endSimulatedMemoryPressure();

unsigned long numberOfIDBTransactions();

unsigned long numberOfLiveNodes();
unsigned long numberOfLiveDocuments();
unsigned long referencingNodeCount(Document document);

0 comments on commit 56e0916

Please sign in to comment.