Diff
Modified: trunk/Source/WebCore/ChangeLog (242135 => 242136)
--- trunk/Source/WebCore/ChangeLog 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebCore/ChangeLog 2019-02-27 18:55:07 UTC (rev 242136)
@@ -1,3 +1,32 @@
+2019-02-27 Sihui Liu <[email protected]>
+
+ Network Process is put to suspended when holding locked IndexedDB files
+ https://bugs.webkit.org/show_bug.cgi?id=195024
+ <rdar://problem/45194169>
+
+ Reviewed by Geoffrey Garen.
+
+ We found network process was suspended when IDBDatabase was being closed in the background database thread,
+ holding locks to its database file. To avoid starvation or deadlock, we need to keep network process alive by
+ taking background assertion in UI process until the closes are done and locks are released.
+
+ * Modules/indexeddb/server/IDBServer.cpp:
+ (WebCore::IDBServer::IDBServer::create):
+ (WebCore::IDBServer::IDBServer::IDBServer):
+ (WebCore::IDBServer::IDBServer::createBackingStore):
+ (WebCore::IDBServer::IDBServer::closeDatabase):
+ (WebCore::IDBServer::IDBServer::didCloseDatabase):
+ * Modules/indexeddb/server/IDBServer.h:
+ (WebCore::IDBServer::IDBServer::create):
+ * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+ (WebCore::IDBServer::UniqueIDBDatabase::performCurrentDeleteOperation):
+ (WebCore::IDBServer::UniqueIDBDatabase::scheduleShutdownForClose):
+ (WebCore::IDBServer::UniqueIDBDatabase::didShutdownForClose):
+ (WebCore::IDBServer::UniqueIDBDatabase::didDeleteBackingStore):
+ (WebCore::IDBServer::UniqueIDBDatabase::immediateCloseForUserDelete):
+ (WebCore::IDBServer::UniqueIDBDatabase::notifyServerAboutClose):
+ * Modules/indexeddb/server/UniqueIDBDatabase.h:
+
2019-02-26 Simon Fraser <[email protected]>
Have a single notion of scroll position in the scrolling tree and derive layoutViewport from it
Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp (242135 => 242136)
--- trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp 2019-02-27 18:55:07 UTC (rev 242136)
@@ -42,26 +42,30 @@
namespace WebCore {
namespace IDBServer {
-Ref<IDBServer> IDBServer::create(IDBBackingStoreTemporaryFileHandler& fileHandler)
+Ref<IDBServer> IDBServer::create(IDBBackingStoreTemporaryFileHandler& fileHandler, WTF::Function<void(bool)>&& isClosingDatabaseCallback)
{
- return adoptRef(*new IDBServer(fileHandler));
+ return adoptRef(*new IDBServer(fileHandler, WTFMove(isClosingDatabaseCallback)));
}
-Ref<IDBServer> IDBServer::create(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler& fileHandler)
+Ref<IDBServer> IDBServer::create(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler& fileHandler, WTF::Function<void(bool)>&& isClosingDatabaseCallback)
{
- return adoptRef(*new IDBServer(databaseDirectoryPath, fileHandler));
+ return adoptRef(*new IDBServer(databaseDirectoryPath, fileHandler, WTFMove(isClosingDatabaseCallback)));
}
-IDBServer::IDBServer(IDBBackingStoreTemporaryFileHandler& fileHandler)
+IDBServer::IDBServer(IDBBackingStoreTemporaryFileHandler& fileHandler, WTF::Function<void(bool)>&& isClosingDatabaseCallback)
: CrossThreadTaskHandler("IndexedDatabase Server")
, m_backingStoreTemporaryFileHandler(fileHandler)
+ , m_isClosingDatabaseCallback(WTFMove(isClosingDatabaseCallback))
+ , m_isClosingDatabaseHysteresis([&](PAL::HysteresisState state) { m_isClosingDatabaseCallback(state == PAL::HysteresisState::Started); })
{
}
-IDBServer::IDBServer(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler& fileHandler)
+IDBServer::IDBServer(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler& fileHandler, WTF::Function<void(bool)>&& isClosingDatabaseCallback)
: CrossThreadTaskHandler("IndexedDatabase Server")
, m_databaseDirectoryPath(databaseDirectoryPath)
, m_backingStoreTemporaryFileHandler(fileHandler)
+ , m_isClosingDatabaseCallback(WTFMove(isClosingDatabaseCallback))
+ , m_isClosingDatabaseHysteresis([&](PAL::HysteresisState state) { m_isClosingDatabaseCallback(state == PAL::HysteresisState::Started); })
{
LOG(IndexedDB, "IDBServer created at path %s", databaseDirectoryPath.utf8().data());
}
@@ -652,6 +656,29 @@
database->setQuota(quota);
}
+void IDBServer::closeDatabase(UniqueIDBDatabase* database)
+{
+ ASSERT(isMainThread());
+ if (m_databaseDirectoryPath.isEmpty())
+ return;
+
+ auto addResult = m_uniqueIDBDatabasesInClose.add(database);
+ if (addResult.isNewEntry && m_uniqueIDBDatabasesInClose.size() == 1)
+ m_isClosingDatabaseHysteresis.start();
+}
+
+void IDBServer::didCloseDatabase(UniqueIDBDatabase* database)
+{
+ ASSERT(isMainThread());
+ if (m_databaseDirectoryPath.isEmpty())
+ return;
+
+ if (m_uniqueIDBDatabasesInClose.remove(database)) {
+ if (m_uniqueIDBDatabasesInClose.isEmpty())
+ m_isClosingDatabaseHysteresis.stop();
+ }
+}
+
} // namespace IDBServer
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h (242135 => 242136)
--- trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h 2019-02-27 18:55:07 UTC (rev 242136)
@@ -31,6 +31,7 @@
#include "IDBDatabaseIdentifier.h"
#include "UniqueIDBDatabase.h"
#include "UniqueIDBDatabaseConnection.h"
+#include <pal/HysteresisActivity.h>
#include <wtf/CrossThreadTaskHandler.h>
#include <wtf/HashMap.h>
#include <wtf/Lock.h>
@@ -54,8 +55,8 @@
class IDBServer : public RefCounted<IDBServer>, public CrossThreadTaskHandler {
public:
- static Ref<IDBServer> create(IDBBackingStoreTemporaryFileHandler&);
- WEBCORE_EXPORT static Ref<IDBServer> create(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler&);
+ static Ref<IDBServer> create(IDBBackingStoreTemporaryFileHandler&, WTF::Function<void(bool)>&& isClosingDatabaseCallback = [](bool) { });
+ WEBCORE_EXPORT static Ref<IDBServer> create(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler&, WTF::Function<void(bool)>&& isClosingDatabaseCallback = [](bool) { });
WEBCORE_EXPORT void registerConnection(IDBConnectionToClient&);
WEBCORE_EXPORT void unregisterConnection(IDBConnectionToClient&);
@@ -109,9 +110,13 @@
uint64_t perOriginQuota() const { return m_perOriginQuota; }
WEBCORE_EXPORT void setPerOriginQuota(uint64_t);
+ void closeDatabase(UniqueIDBDatabase*);
+ void didCloseDatabase(UniqueIDBDatabase*);
+ void hysteresisUpdated(PAL::HysteresisState);
+
private:
- IDBServer(IDBBackingStoreTemporaryFileHandler&);
- IDBServer(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler&);
+ IDBServer(IDBBackingStoreTemporaryFileHandler&, WTF::Function<void(bool)>&&);
+ IDBServer(const String& databaseDirectoryPath, IDBBackingStoreTemporaryFileHandler&, WTF::Function<void(bool)>&&);
UniqueIDBDatabase& getOrCreateUniqueIDBDatabase(const IDBDatabaseIdentifier&);
@@ -124,6 +129,7 @@
HashMap<uint64_t, RefPtr<IDBConnectionToClient>> m_connectionMap;
HashMap<IDBDatabaseIdentifier, std::unique_ptr<UniqueIDBDatabase>> m_uniqueIDBDatabaseMap;
+ HashSet<UniqueIDBDatabase*> m_uniqueIDBDatabasesInClose;
HashMap<uint64_t, UniqueIDBDatabaseConnection*> m_databaseConnections;
HashMap<IDBResourceIdentifier, UniqueIDBDatabaseTransaction*> m_transactions;
@@ -134,6 +140,9 @@
IDBBackingStoreTemporaryFileHandler& m_backingStoreTemporaryFileHandler;
uint64_t m_perOriginQuota { defaultPerOriginQuota };
+
+ WTF::Function<void(bool)> m_isClosingDatabaseCallback;
+ PAL::HysteresisActivity m_isClosingDatabaseHysteresis;
};
} // namespace IDBServer
Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp (242135 => 242136)
--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp 2019-02-27 18:55:07 UTC (rev 242136)
@@ -226,6 +226,7 @@
didDeleteBackingStore(0);
else {
m_deleteBackingStoreInProgress = true;
+ notifyServerAboutClose(CloseState::Start);
postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::deleteBackingStore, m_identifier));
}
}
@@ -278,6 +279,7 @@
RELEASE_ASSERT(!m_owningPointerForClose);
m_owningPointerForClose = m_server.closeAndTakeUniqueIDBDatabase(*this);
+ notifyServerAboutClose(CloseState::Start);
postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::shutdownForClose));
}
@@ -305,6 +307,7 @@
{
ASSERT(m_databaseReplyQueue.isEmpty());
m_databaseReplyQueue.kill();
+ notifyServerAboutClose(CloseState::Done);
}
void UniqueIDBDatabase::didDeleteBackingStore(uint64_t deletedVersion)
@@ -340,6 +343,7 @@
if (m_hardClosedForUserDelete)
return;
+ notifyServerAboutClose(CloseState::Done);
invokeOperationAndTransactionTimer();
}
@@ -1891,6 +1895,7 @@
if (m_owningPointerForClose)
return;
+ notifyServerAboutClose(CloseState::Start);
// Otherwise, this database is still potentially active.
// So we'll have it own itself and then perform a clean unconditional delete on the background thread.
m_owningPointerForClose = m_server.closeAndTakeUniqueIDBDatabase(*this);
@@ -1966,6 +1971,19 @@
m_backingStore->setQuota(quota);
}
+void UniqueIDBDatabase::notifyServerAboutClose(CloseState state)
+{
+ ASSERT(isMainThread());
+#if PLATFORM(IOS_FAMILY)
+ if (state == CloseState::Start)
+ m_server.closeDatabase(this);
+ else
+ m_server.didCloseDatabase(this);
+#else
+ UNUSED_PARAM(state);
+#endif
+}
+
} // namespace IDBServer
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h (242135 => 242136)
--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h 2019-02-27 18:55:07 UTC (rev 242136)
@@ -121,6 +121,8 @@
void setQuota(uint64_t);
private:
+ enum class CloseState { Start, Done };
+
void handleDatabaseOperations();
void handleCurrentOperation();
void performCurrentOpenOperation();
@@ -225,6 +227,8 @@
void maybeFinishHardClose();
bool isDoneWithHardClose();
+ void notifyServerAboutClose(CloseState);
+
IDBServer& m_server;
IDBDatabaseIdentifier m_identifier;
Modified: trunk/Source/WebKit/ChangeLog (242135 => 242136)
--- trunk/Source/WebKit/ChangeLog 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebKit/ChangeLog 2019-02-27 18:55:07 UTC (rev 242136)
@@ -1,3 +1,21 @@
+2019-02-27 Sihui Liu <[email protected]>
+
+ Network Process is put to suspended when holding locked IndexedDB files
+ https://bugs.webkit.org/show_bug.cgi?id=195024
+ <rdar://problem/45194169>
+
+ Reviewed by Geoffrey Garen.
+
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::idbServer):
+ (WebKit::NetworkProcess::notifyHoldingLockedFiles):
+ * NetworkProcess/NetworkProcess.h:
+ * UIProcess/Network/NetworkProcessProxy.cpp:
+ (WebKit::NetworkProcessProxy::didClose):
+ (WebKit::NetworkProcessProxy::setIsIDBDatabaseHoldingLockedFiles):
+ * UIProcess/Network/NetworkProcessProxy.h:
+ * UIProcess/Network/NetworkProcessProxy.messages.in:
+
2019-02-26 Simon Fraser <[email protected]>
Have a single notion of scroll position in the scrolling tree and derive layoutViewport from it
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (242135 => 242136)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2019-02-27 18:55:07 UTC (rev 242136)
@@ -1984,7 +1984,9 @@
// If there's not, then where did this PAL::SessionID come from?
ASSERT(!path.isEmpty());
- addResult.iterator->value = IDBServer::IDBServer::create(path, *this);
+ addResult.iterator->value = IDBServer::IDBServer::create(path, *this, [this](bool isHoldingLockedFiles) {
+ notifyHoldingLockedFiles(isHoldingLockedFiles);
+ });
addResult.iterator->value->setPerOriginQuota(m_idbPerOriginQuota);
return *addResult.iterator->value;
}
@@ -2322,4 +2324,9 @@
completionHandler();
}
+void NetworkProcess::notifyHoldingLockedFiles(bool isIDBDatabaseHoldingLockedFiles)
+{
+ parentProcessConnection()->send(Messages::NetworkProcessProxy::SetIsIDBDatabaseHoldingLockedFiles(isIDBDatabaseHoldingLockedFiles), 0);
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (242135 => 242136)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h 2019-02-27 18:55:07 UTC (rev 242136)
@@ -389,6 +389,7 @@
void syncAllCookies();
void didSyncAllCookies();
+ void notifyHoldingLockedFiles(bool isIDBDatabaseHoldingLockedFiles);
#if USE(SOUP)
void setIgnoreTLSErrors(bool);
void userPreferredLanguagesChanged(const Vector<String>&);
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (242135 => 242136)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp 2019-02-27 18:55:07 UTC (rev 242136)
@@ -269,6 +269,7 @@
#endif
m_tokenForHoldingLockedFiles = nullptr;
+ m_tokenForIDBDatabaseHoldingLockedFiles = nullptr;
m_syncAllCookiesToken = nullptr;
m_syncAllCookiesCounter = 0;
@@ -981,6 +982,19 @@
}
}
+void NetworkProcessProxy::setIsIDBDatabaseHoldingLockedFiles(bool isIDBDatabaseHoldingLockedFiles)
+{
+ if (!isIDBDatabaseHoldingLockedFiles) {
+ RELEASE_LOG(ProcessSuspension, "UIProcess is releasing a background assertion because the Network process is no longer holding locked files for IDBDatabase");
+ m_tokenForIDBDatabaseHoldingLockedFiles = nullptr;
+ return;
+ }
+ if (!m_tokenForIDBDatabaseHoldingLockedFiles) {
+ RELEASE_LOG(ProcessSuspension, "UIProcess is taking a background assertion because the Network process is holding locked files for IDBDatabase");
+ m_tokenForIDBDatabaseHoldingLockedFiles = m_throttler.backgroundActivityToken();
+ }
+}
+
void NetworkProcessProxy::syncAllCookies()
{
send(Messages::NetworkProcess::SyncAllCookies(), 0);
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (242135 => 242136)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h 2019-02-27 18:55:07 UTC (rev 242136)
@@ -136,7 +136,8 @@
void sendProcessDidTransitionToBackground();
void setIsHoldingLockedFiles(bool);
-
+ void setIsIDBDatabaseHoldingLockedFiles(bool);
+
void syncAllCookies();
void didSyncAllCookies();
@@ -230,6 +231,7 @@
#endif
ProcessThrottler m_throttler;
ProcessThrottler::BackgroundActivityToken m_tokenForHoldingLockedFiles;
+ ProcessThrottler::BackgroundActivityToken m_tokenForIDBDatabaseHoldingLockedFiles;
ProcessThrottler::BackgroundActivityToken m_syncAllCookiesToken;
unsigned m_syncAllCookiesCounter { 0 };
Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in (242135 => 242136)
--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in 2019-02-27 18:49:24 UTC (rev 242135)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in 2019-02-27 18:55:07 UTC (rev 242136)
@@ -33,6 +33,7 @@
ProcessReadyToSuspend()
SetIsHoldingLockedFiles(bool isHoldingLockedFiles)
+ SetIsIDBDatabaseHoldingLockedFiles(bool isIDBDatabaseHoldingLockedFiles)
# Diagnostic messages logging
LogDiagnosticMessage(uint64_t pageID, String message, String description, enum:bool WebCore::ShouldSample shouldSample)