Changeset 244687 in webkit
- Timestamp:
- Apr 26, 2019 9:08:40 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r244676 r244687 1 2019-04-26 Sihui Liu <sihui_liu@apple.com> 2 3 Stop IDB transactions to release locked database files when network process is ready to suspend 4 https://bugs.webkit.org/show_bug.cgi?id=196372 5 <rdar://problem/48930116> 6 7 Reviewed by Brady Eidson. 8 9 Provide a method to suspend the thread and block main thread until the thread is suspended. 10 11 * wtf/CrossThreadTaskHandler.cpp: 12 (WTF::CrossThreadTaskHandler::taskRunLoop): 13 (WTF::CrossThreadTaskHandler::suspendAndWait): 14 (WTF::CrossThreadTaskHandler::resume): 15 * wtf/CrossThreadTaskHandler.h: 16 1 17 2019-04-25 Fujii Hironori <Hironori.Fujii@sony.com> 2 18 -
trunk/Source/WTF/wtf/CrossThreadTaskHandler.cpp
r237099 r244687 69 69 } 70 70 71 while (!m_taskQueue.isKilled()) 71 while (!m_taskQueue.isKilled()) { 72 72 m_taskQueue.waitForMessage().performTask(); 73 74 Locker<Lock> shouldSuspendLocker(m_shouldSuspendLock); 75 while (m_shouldSuspend) { 76 m_suspendedLock.lock(); 77 if (!m_suspended) { 78 m_suspended = true; 79 m_suspendedCondition.notifyOne(); 80 } 81 m_suspendedLock.unlock(); 82 m_shouldSuspendCondition.wait(m_shouldSuspendLock); 83 } 84 } 73 85 } 74 86 … … 84 96 } 85 97 98 void CrossThreadTaskHandler::suspendAndWait() 99 { 100 ASSERT(isMainThread()); 101 { 102 Locker<Lock> locker(m_shouldSuspendLock); 103 m_shouldSuspend = true; 104 } 105 106 // Post an empty task to ensure database thread knows m_shouldSuspend and sets m_suspended. 107 postTask(CrossThreadTask([]() { })); 108 109 Locker<Lock> locker(m_suspendedLock); 110 while (!m_suspended) 111 m_suspendedCondition.wait(m_suspendedLock); 112 } 113 114 void CrossThreadTaskHandler::resume() 115 { 116 ASSERT(isMainThread()); 117 Locker<Lock> locker(m_shouldSuspendLock); 118 if (m_shouldSuspend) { 119 m_suspendedLock.lock(); 120 if (m_suspended) 121 m_suspended = false; 122 m_suspendedLock.unlock(); 123 m_shouldSuspend = false; 124 m_shouldSuspendCondition.notifyOne(); 125 } 126 } 86 127 87 128 } // namespace WTF -
trunk/Source/WTF/wtf/CrossThreadTaskHandler.h
r225998 r244687 45 45 WTF_EXPORT_PRIVATE void postTask(CrossThreadTask&&); 46 46 WTF_EXPORT_PRIVATE void postTaskReply(CrossThreadTask&&); 47 WTF_EXPORT_PRIVATE void suspendAndWait(); 48 WTF_EXPORT_PRIVATE void resume(); 47 49 48 50 private: … … 54 56 bool m_mainThreadReplyScheduled { false }; 55 57 58 bool m_shouldSuspend { false }; 59 Condition m_shouldSuspendCondition; 60 Lock m_shouldSuspendLock; 61 62 bool m_suspended { false }; 63 Condition m_suspendedCondition; 64 Lock m_suspendedLock; 65 56 66 CrossThreadQueue<CrossThreadTask> m_taskQueue; 57 67 CrossThreadQueue<CrossThreadTask> m_taskReplyQueue; -
trunk/Source/WebCore/ChangeLog
r244684 r244687 1 2019-04-26 Sihui Liu <sihui_liu@apple.com> 2 3 Stop IDB transactions to release locked database files when network process is ready to suspend 4 https://bugs.webkit.org/show_bug.cgi?id=196372 5 <rdar://problem/48930116> 6 7 Reviewed by Brady Eidson. 8 9 Suspend IDB database thread and finish ongoing IDB transactions on the main thread before suspending network 10 process. 11 12 API test: IndexedDB.IndexedDBSuspendImminently 13 14 * Modules/indexeddb/server/IDBBackingStore.h: 15 * Modules/indexeddb/server/IDBServer.cpp: 16 (WebCore::IDBServer::IDBServer::tryStop): 17 (WebCore::IDBServer::IDBServer::resume): 18 * Modules/indexeddb/server/IDBServer.h: 19 * Modules/indexeddb/server/MemoryIDBBackingStore.h: 20 * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp: Remove some error log messages, because now we may try 21 performing database operations without an active transaction if the transaction is finished on the main thread. 22 (WebCore::IDBServer::SQLiteIDBBackingStore::createObjectStore): 23 (WebCore::IDBServer::SQLiteIDBBackingStore::deleteObjectStore): 24 (WebCore::IDBServer::SQLiteIDBBackingStore::renameObjectStore): 25 (WebCore::IDBServer::SQLiteIDBBackingStore::clearObjectStore): 26 (WebCore::IDBServer::SQLiteIDBBackingStore::createIndex): 27 (WebCore::IDBServer::SQLiteIDBBackingStore::deleteIndex): 28 (WebCore::IDBServer::SQLiteIDBBackingStore::renameIndex): 29 (WebCore::IDBServer::SQLiteIDBBackingStore::keyExistsInObjectStore): 30 (WebCore::IDBServer::SQLiteIDBBackingStore::deleteRange): 31 (WebCore::IDBServer::SQLiteIDBBackingStore::addRecord): 32 (WebCore::IDBServer::SQLiteIDBBackingStore::getRecord): 33 (WebCore::IDBServer::SQLiteIDBBackingStore::getAllObjectStoreRecords): 34 (WebCore::IDBServer::SQLiteIDBBackingStore::getAllIndexRecords): 35 (WebCore::IDBServer::SQLiteIDBBackingStore::getIndexRecord): 36 (WebCore::IDBServer::SQLiteIDBBackingStore::getCount): 37 (WebCore::IDBServer::SQLiteIDBBackingStore::generateKeyNumber): 38 (WebCore::IDBServer::SQLiteIDBBackingStore::revertGeneratedKeyNumber): 39 (WebCore::IDBServer::SQLiteIDBBackingStore::maybeUpdateKeyGeneratorNumber): 40 (WebCore::IDBServer::SQLiteIDBBackingStore::openCursor): 41 (WebCore::IDBServer::SQLiteIDBBackingStore::iterateCursor): 42 (WebCore::IDBServer::SQLiteIDBBackingStore::hasTransaction const): 43 * Modules/indexeddb/server/SQLiteIDBBackingStore.h: 44 * Modules/indexeddb/server/UniqueIDBDatabase.cpp: 45 (WebCore::IDBServer::UniqueIDBDatabase::prepareToFinishTransaction): 46 (WebCore::IDBServer::UniqueIDBDatabase::commitTransactionAfterQuotaCheck): 47 (WebCore::IDBServer::UniqueIDBDatabase::didPerformCommitTransaction): 48 (WebCore::IDBServer::UniqueIDBDatabase::abortTransaction): 49 (WebCore::IDBServer::UniqueIDBDatabase::didPerformAbortTransaction): 50 (WebCore::IDBServer::UniqueIDBDatabase::abortTransactionOnMainThread): 51 (WebCore::IDBServer::UniqueIDBDatabase::commitTransactionOnMainThread): 52 (WebCore::IDBServer::UniqueIDBDatabase::finishActiveTransactions): 53 * Modules/indexeddb/server/UniqueIDBDatabase.h: 54 * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h: 55 (WebCore::IDBServer::UniqueIDBDatabaseTransaction::setState): 56 (WebCore::IDBServer::UniqueIDBDatabaseTransaction::state const): 57 (WebCore::IDBServer::UniqueIDBDatabaseTransaction::setResult): 58 (WebCore::IDBServer::UniqueIDBDatabaseTransaction::result const): 59 * platform/sql/SQLiteDatabaseTracker.cpp: 60 (WebCore::SQLiteDatabaseTracker::hasTransactionInProgress): 61 * platform/sql/SQLiteDatabaseTracker.h: 62 1 63 2019-04-26 Takashi Komori <Takashi.Komori@sony.com> 2 64 -
trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h
r242911 r244687 102 102 virtual uint64_t databasesSizeForOrigin() const = 0; 103 103 virtual void setQuota(uint64_t) = 0; 104 105 virtual bool hasTransaction(const IDBResourceIdentifier&) const = 0; 104 106 protected: 105 107 IDBBackingStore() { RELEASE_ASSERT(!isMainThread()); } -
trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp
r244077 r244687 34 34 #include "MemoryIDBBackingStore.h" 35 35 #include "SQLiteDatabase.h" 36 #include "SQLiteDatabaseTracker.h" 36 37 #include "SQLiteFileSystem.h" 37 38 #include "SQLiteIDBBackingStore.h" … … 829 830 } 830 831 832 void IDBServer::tryStop(ShouldForceStop shouldForceStop) 833 { 834 // Only stop non-ephemeral IDBServers that can hold locked database files. 835 if (m_sessionID.isEphemeral()) 836 return; 837 838 suspendAndWait(); 839 if (shouldForceStop == ShouldForceStop::No && SQLiteDatabaseTracker::hasTransactionInProgress()) { 840 CrossThreadTaskHandler::resume(); 841 return; 842 } 843 844 for (auto& database : m_uniqueIDBDatabaseMap.values()) 845 database->finishActiveTransactions(); 846 } 847 848 void IDBServer::resume() 849 { 850 if (m_sessionID.isEphemeral()) 851 return; 852 853 CrossThreadTaskHandler::resume(); 854 } 855 831 856 } // namespace IDBServer 832 857 } // namespace WebCore -
trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h
r244077 r244687 59 59 class IDBBackingStoreTemporaryFileHandler; 60 60 61 enum class ShouldForceStop : bool { No, Yes }; 62 61 63 class IDBServer : public RefCounted<IDBServer>, public CrossThreadTaskHandler, public CanMakeWeakPtr<IDBServer> { 62 64 public: … … 125 127 void initializeQuotaUser(const ClientOrigin& origin) { ensureQuotaUser(origin); } 126 128 129 WEBCORE_EXPORT void tryStop(ShouldForceStop); 130 WEBCORE_EXPORT void resume(); 131 127 132 private: 128 133 IDBServer(PAL::SessionID, IDBBackingStoreTemporaryFileHandler&, QuotaManagerGetter&&); -
trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h
r242911 r244687 86 86 void restoreObjectStoreForVersionChangeAbort(Ref<MemoryObjectStore>&&); 87 87 88 bool hasTransaction(const IDBResourceIdentifier& identifier) const final { return m_transactions.contains(identifier); } 89 88 90 private: 89 91 RefPtr<MemoryObjectStore> takeObjectStoreByIdentifier(uint64_t identifier); -
trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp
r244436 r244687 1006 1006 1007 1007 auto* transaction = m_transactions.get(transactionIdentifier); 1008 if (!transaction || !transaction->inProgress()) { 1009 LOG_ERROR("Attempt to create an object store without an in-progress transaction"); 1008 if (!transaction || !transaction->inProgress()) 1010 1009 return IDBError { UnknownError, "Attempt to create an object store without an in-progress transaction"_s }; 1011 } 1010 1012 1011 if (transaction->mode() != IDBTransactionMode::Versionchange) { 1013 1012 LOG_ERROR("Attempt to create an object store in a non-version-change transaction"); … … 1062 1061 1063 1062 auto* transaction = m_transactions.get(transactionIdentifier); 1064 if (!transaction || !transaction->inProgress()) { 1065 LOG_ERROR("Attempt to delete an object store without an in-progress transaction"); 1063 if (!transaction || !transaction->inProgress()) 1066 1064 return IDBError { UnknownError, "Attempt to delete an object store without an in-progress transaction"_s }; 1067 } 1065 1068 1066 if (transaction->mode() != IDBTransactionMode::Versionchange) { 1069 1067 LOG_ERROR("Attempt to delete an object store in a non-version-change transaction"); … … 1154 1152 1155 1153 auto* transaction = m_transactions.get(transactionIdentifier); 1156 if (!transaction || !transaction->inProgress()) { 1157 LOG_ERROR("Attempt to rename an object store without an in-progress transaction"); 1154 if (!transaction || !transaction->inProgress()) 1158 1155 return IDBError { UnknownError, "Attempt to rename an object store without an in-progress transaction"_s }; 1159 } 1156 1160 1157 if (transaction->mode() != IDBTransactionMode::Versionchange) { 1161 1158 LOG_ERROR("Attempt to rename an object store in a non-version-change transaction"); … … 1189 1186 1190 1187 auto* transaction = m_transactions.get(transactionIdentifier); 1191 if (!transaction || !transaction->inProgress()) { 1192 LOG_ERROR("Attempt to clear an object store without an in-progress transaction"); 1188 if (!transaction || !transaction->inProgress()) 1193 1189 return IDBError { UnknownError, "Attempt to clear an object store without an in-progress transaction"_s }; 1194 } 1190 1195 1191 if (transaction->mode() == IDBTransactionMode::Readonly) { 1196 1192 LOG_ERROR("Attempt to clear an object store in a read-only transaction"); … … 1230 1226 1231 1227 auto* transaction = m_transactions.get(transactionIdentifier); 1232 if (!transaction || !transaction->inProgress()) { 1233 LOG_ERROR("Attempt to create an index without an in-progress transaction"); 1228 if (!transaction || !transaction->inProgress()) 1234 1229 return IDBError { UnknownError, "Attempt to create an index without an in-progress transaction"_s }; 1235 } 1230 1236 1231 if (transaction->mode() != IDBTransactionMode::Versionchange) { 1237 1232 LOG_ERROR("Attempt to create an index in a non-version-change transaction"); … … 1423 1418 1424 1419 auto* transaction = m_transactions.get(transactionIdentifier); 1425 if (!transaction || !transaction->inProgress()) { 1426 LOG_ERROR("Attempt to delete index without an in-progress transaction"); 1420 if (!transaction || !transaction->inProgress()) 1427 1421 return IDBError { UnknownError, "Attempt to delete index without an in-progress transaction"_s }; 1428 }1429 1422 1430 1423 if (transaction->mode() != IDBTransactionMode::Versionchange) { … … 1478 1471 1479 1472 auto* transaction = m_transactions.get(transactionIdentifier); 1480 if (!transaction || !transaction->inProgress()) { 1481 LOG_ERROR("Attempt to rename an index without an in-progress transaction"); 1473 if (!transaction || !transaction->inProgress()) 1482 1474 return IDBError { UnknownError, "Attempt to rename an index without an in-progress transaction"_s }; 1483 }1484 1475 1485 1476 if (transaction->mode() != IDBTransactionMode::Versionchange) { … … 1517 1508 1518 1509 auto* transaction = m_transactions.get(transactionIdentifier); 1519 if (!transaction || !transaction->inProgress()) { 1520 LOG_ERROR("Attempt to see if key exists in objectstore without an in-progress transaction"); 1510 if (!transaction || !transaction->inProgress()) 1521 1511 return IDBError { UnknownError, "Attempt to see if key exists in objectstore without an in-progress transaction"_s }; 1522 }1523 1512 1524 1513 RefPtr<SharedBuffer> keyBuffer = serializeIDBKeyData(keyData); … … 1692 1681 1693 1682 auto* transaction = m_transactions.get(transactionIdentifier); 1694 if (!transaction || !transaction->inProgress()) { 1695 LOG_ERROR("Attempt to delete range from database without an in-progress transaction"); 1683 if (!transaction || !transaction->inProgress()) 1696 1684 return IDBError { UnknownError, "Attempt to delete range from database without an in-progress transaction"_s }; 1697 } 1685 1698 1686 if (transaction->mode() == IDBTransactionMode::Readonly) { 1699 1687 LOG_ERROR("Attempt to delete records from an object store in a read-only transaction"); … … 1815 1803 1816 1804 auto* transaction = m_transactions.get(transactionIdentifier); 1817 if (!transaction || !transaction->inProgress()) { 1818 LOG_ERROR("Attempt to store a record in an object store without an in-progress transaction"); 1805 if (!transaction || !transaction->inProgress()) 1819 1806 return IDBError { UnknownError, "Attempt to store a record in an object store without an in-progress transaction"_s }; 1820 } 1807 1821 1808 if (transaction->mode() == IDBTransactionMode::Readonly) { 1822 1809 LOG_ERROR("Attempt to store a record in an object store in a read-only transaction"); … … 1984 1971 1985 1972 auto* transaction = m_transactions.get(transactionIdentifier); 1986 if (!transaction || !transaction->inProgress()) { 1987 LOG_ERROR("Attempt to get a record from database without an in-progress transaction"); 1973 if (!transaction || !transaction->inProgress()) 1988 1974 return IDBError { UnknownError, "Attempt to get a record from database without an in-progress transaction"_s }; 1989 }1990 1975 1991 1976 auto key = keyRange.lowerKey; … … 2161 2146 2162 2147 auto* transaction = m_transactions.get(transactionIdentifier); 2163 if (!transaction || !transaction->inProgress()) { 2164 LOG_ERROR("Attempt to get records from database without an in-progress transaction"); 2148 if (!transaction || !transaction->inProgress()) 2165 2149 return IDBError { UnknownError, "Attempt to get records from database without an in-progress transaction"_s }; 2166 }2167 2150 2168 2151 auto key = getAllRecordsData.keyRangeData.lowerKey; … … 2257 2240 2258 2241 auto* transaction = m_transactions.get(transactionIdentifier); 2259 if (!transaction || !transaction->inProgress()) { 2260 LOG_ERROR("Attempt to get all index records from database without an in-progress transaction"); 2242 if (!transaction || !transaction->inProgress()) 2261 2243 return IDBError { UnknownError, "Attempt to get all index records from database without an in-progress transaction"_s }; 2262 }2263 2244 2264 2245 auto cursor = transaction->maybeOpenBackingStoreCursor(getAllRecordsData.objectStoreIdentifier, getAllRecordsData.indexIdentifier, getAllRecordsData.keyRangeData); … … 2307 2288 2308 2289 auto* transaction = m_transactions.get(transactionIdentifier); 2309 if (!transaction || !transaction->inProgress()) { 2310 LOG_ERROR("Attempt to get an index record from database without an in-progress transaction"); 2290 if (!transaction || !transaction->inProgress()) 2311 2291 return IDBError { UnknownError, "Attempt to get an index record from database without an in-progress transaction"_s }; 2312 }2313 2292 2314 2293 if (range.isExactlyOneKey()) … … 2413 2392 2414 2393 auto* transaction = m_transactions.get(transactionIdentifier); 2415 if (!transaction || !transaction->inProgress()) { 2416 LOG_ERROR("Attempt to get count from database without an in-progress transaction"); 2394 if (!transaction || !transaction->inProgress()) 2417 2395 return IDBError { UnknownError, "Attempt to get count from database without an in-progress transaction"_s }; 2418 }2419 2396 2420 2397 auto cursor = transaction->maybeOpenBackingStoreCursor(objectStoreIdentifier, indexIdentifier, range); … … 2476 2453 2477 2454 auto* transaction = m_transactions.get(transactionIdentifier); 2478 if (!transaction || !transaction->inProgress()) { 2479 LOG_ERROR("Attempt to generate key in database without an in-progress transaction"); 2455 if (!transaction || !transaction->inProgress()) 2480 2456 return IDBError { UnknownError, "Attempt to generate key in database without an in-progress transaction"_s }; 2481 } 2457 2482 2458 if (transaction->mode() == IDBTransactionMode::Readonly) { 2483 2459 LOG_ERROR("Attempt to generate key in a read-only transaction"); … … 2505 2481 2506 2482 auto* transaction = m_transactions.get(transactionIdentifier); 2507 if (!transaction || !transaction->inProgress()) { 2508 LOG_ERROR("Attempt to revert key generator value in database without an in-progress transaction"); 2483 if (!transaction || !transaction->inProgress()) 2509 2484 return IDBError { UnknownError, "Attempt to revert key generator value in database without an in-progress transaction"_s }; 2510 } 2485 2511 2486 if (transaction->mode() == IDBTransactionMode::Readonly) { 2512 2487 LOG_ERROR("Attempt to revert key generator value in a read-only transaction"); … … 2526 2501 2527 2502 auto* transaction = m_transactions.get(transactionIdentifier); 2528 if (!transaction || !transaction->inProgress()) { 2529 LOG_ERROR("Attempt to update key generator value in database without an in-progress transaction"); 2503 if (!transaction || !transaction->inProgress()) 2530 2504 return IDBError { UnknownError, "Attempt to update key generator value in database without an in-progress transaction"_s }; 2531 } 2505 2532 2506 if (transaction->mode() == IDBTransactionMode::Readonly) { 2533 2507 LOG_ERROR("Attempt to update key generator value in a read-only transaction"); … … 2552 2526 2553 2527 auto* transaction = m_transactions.get(transactionIdentifier); 2554 if (!transaction || !transaction->inProgress()) { 2555 LOG_ERROR("Attempt to open a cursor in database without an in-progress transaction"); 2528 if (!transaction || !transaction->inProgress()) 2556 2529 return IDBError { UnknownError, "Attempt to open a cursor in database without an in-progress transaction"_s }; 2557 }2558 2530 2559 2531 auto* cursor = transaction->maybeOpenCursor(info); … … 2586 2558 ASSERT_UNUSED(transactionIdentifier, cursor->transaction()->transactionIdentifier() == transactionIdentifier); 2587 2559 2588 if (!cursor->transaction() || !cursor->transaction()->inProgress()) { 2589 LOG_ERROR("Attempt to iterate a cursor without an in-progress transaction"); 2560 if (!cursor->transaction() || !cursor->transaction()->inProgress()) 2590 2561 return IDBError { UnknownError, "Attempt to iterate a cursor without an in-progress transaction"_s }; 2591 }2592 2562 2593 2563 auto key = data.keyData; … … 2719 2689 } 2720 2690 2691 bool SQLiteIDBBackingStore::hasTransaction(const IDBResourceIdentifier& transactionIdentifier) const 2692 { 2693 ASSERT(isMainThread()); 2694 return m_transactions.contains(transactionIdentifier); 2695 } 2696 2721 2697 } // namespace IDBServer 2722 2698 } // namespace WebCore -
trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h
r243019 r244687 101 101 static String databaseNameFromFile(const String&); 102 102 103 bool hasTransaction(const IDBResourceIdentifier&) const final; 103 104 private: 104 105 String filenameForDatabaseName() const; -
trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp
r244436 r244687 1568 1568 } 1569 1569 1570 bool UniqueIDBDatabase::prepareToFinishTransaction(UniqueIDBDatabaseTransaction& transaction )1570 bool UniqueIDBDatabase::prepareToFinishTransaction(UniqueIDBDatabaseTransaction& transaction, UniqueIDBDatabaseTransaction::State state) 1571 1571 { 1572 1572 auto takenTransaction = m_inProgressTransactions.take(transaction.info().identifier()); … … 1575 1575 1576 1576 ASSERT(!m_finishingTransactions.contains(transaction.info().identifier())); 1577 takenTransaction->setState(state); 1577 1578 m_finishingTransactions.set(transaction.info().identifier(), WTFMove(takenTransaction)); 1578 1579 … … 1602 1603 return; 1603 1604 1604 if (!prepareToFinishTransaction(transaction )) {1605 if (!prepareToFinishTransaction(transaction, UniqueIDBDatabaseTransaction::State::Committing)) { 1605 1606 if (!m_openDatabaseConnections.contains(&transaction.databaseConnection())) { 1606 1607 // This database connection is closing or has already closed, so there is no point in messaging back to it about the commit failing. … … 1630 1631 LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCommitTransaction - %s", transactionIdentifier.loggingString().utf8().data()); 1631 1632 1632 performErrorCallback(callbackIdentifier, error); 1633 IDBError result = error; 1634 auto transaction = m_finishingTransactions.get(transactionIdentifier); 1635 switch (transaction->state()) { 1636 case UniqueIDBDatabaseTransaction::State::Aborted: 1637 result = IDBError { UnknownError, "Transaction is already aborted"_s }; 1638 break; 1639 case UniqueIDBDatabaseTransaction::State::Committed: 1640 result = transaction->result(); 1641 break; 1642 case UniqueIDBDatabaseTransaction::State::Committing: 1643 break; 1644 case UniqueIDBDatabaseTransaction::State::Running: 1645 case UniqueIDBDatabaseTransaction::State::Aborting: 1646 ASSERT_NOT_REACHED(); 1647 } 1648 1649 performErrorCallback(callbackIdentifier, result); 1633 1650 1634 1651 transactionCompleted(m_finishingTransactions.take(transactionIdentifier)); … … 1657 1674 return; 1658 1675 1659 if (!prepareToFinishTransaction(transaction )) {1676 if (!prepareToFinishTransaction(transaction, UniqueIDBDatabaseTransaction::State::Aborting)) { 1660 1677 if (!m_openDatabaseConnections.contains(&transaction.databaseConnection())) { 1661 1678 // This database connection is closing or has already closed, so there is no point in messaging back to it about the abort failing. … … 1714 1731 } 1715 1732 1716 performErrorCallback(callbackIdentifier, error); 1733 IDBError result = transaction->state() == UniqueIDBDatabaseTransaction::State::Aborted ? transaction->result() : error; 1734 performErrorCallback(callbackIdentifier, result); 1717 1735 1718 1736 transactionCompleted(WTFMove(transaction)); … … 2278 2296 } 2279 2297 2298 void UniqueIDBDatabase::abortTransactionOnMainThread(UniqueIDBDatabaseTransaction& transaction) 2299 { 2300 transaction.setResult(m_backingStore->abortTransaction(transaction.info().identifier())); 2301 transaction.setState(UniqueIDBDatabaseTransaction::State::Aborted); 2302 } 2303 2304 void UniqueIDBDatabase::commitTransactionOnMainThread(UniqueIDBDatabaseTransaction& transaction) 2305 { 2306 transaction.setResult(m_backingStore->commitTransaction(transaction.info().identifier())); 2307 transaction.setState(UniqueIDBDatabaseTransaction::State::Committed); 2308 } 2309 2310 void UniqueIDBDatabase::finishActiveTransactions() 2311 { 2312 ASSERT(isMainThread()); 2313 2314 for (auto& identifier : copyToVector(m_inProgressTransactions.keys())) { 2315 auto transaction = m_inProgressTransactions.get(identifier); 2316 abortTransactionOnMainThread(*transaction); 2317 } 2318 2319 for (auto& identifier : copyToVector(m_finishingTransactions.keys())) { 2320 if (!m_backingStore->hasTransaction(identifier)) 2321 continue; 2322 2323 auto transaction = m_finishingTransactions.get(identifier); 2324 switch (transaction->state()) { 2325 case UniqueIDBDatabaseTransaction::State::Aborting: 2326 abortTransactionOnMainThread(*transaction); 2327 break; 2328 case UniqueIDBDatabaseTransaction::State::Committing: 2329 commitTransactionOnMainThread(*transaction); 2330 break; 2331 case UniqueIDBDatabaseTransaction::State::Running: 2332 case UniqueIDBDatabaseTransaction::State::Aborted: 2333 case UniqueIDBDatabaseTransaction::State::Committed: 2334 ASSERT_NOT_REACHED(); 2335 } 2336 } 2337 } 2338 2280 2339 } // namespace IDBServer 2281 2340 } // namespace WebCore -
trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h
r244077 r244687 128 128 void setQuota(uint64_t); 129 129 130 void finishActiveTransactions(); 131 130 132 private: 131 133 void handleDatabaseOperations(); … … 238 240 RefPtr<UniqueIDBDatabaseTransaction> takeNextRunnableTransaction(bool& hadDeferredTransactions); 239 241 240 bool prepareToFinishTransaction(UniqueIDBDatabaseTransaction&); 242 bool prepareToFinishTransaction(UniqueIDBDatabaseTransaction&, UniqueIDBDatabaseTransaction::State); 243 void abortTransactionOnMainThread(UniqueIDBDatabaseTransaction&); 244 void commitTransactionOnMainThread(UniqueIDBDatabaseTransaction&); 241 245 242 246 void clearStalePendingOpenDBRequests(); -
trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h
r244115 r244687 57 57 class UniqueIDBDatabaseTransaction : public RefCounted<UniqueIDBDatabaseTransaction> { 58 58 public: 59 enum class State { Running, Aborting, Committing, Aborted, Committed }; 60 59 61 static Ref<UniqueIDBDatabaseTransaction> create(UniqueIDBDatabaseConnection&, const IDBTransactionInfo&); 60 62 … … 91 93 const Vector<uint64_t>& objectStoreIdentifiers(); 92 94 95 void setState(State state) { m_state = state; } 96 State state() const { return m_state; } 97 void setResult(const IDBError& error) { m_result = error; } 98 const IDBError& result() const { return m_result; } 99 93 100 private: 94 101 UniqueIDBDatabaseTransaction(UniqueIDBDatabaseConnection&, const IDBTransactionInfo&); … … 101 108 102 109 Vector<uint64_t> m_objectStoreIdentifiers; 110 111 State m_state { State::Running }; 112 IDBError m_result; 103 113 }; 104 114 -
trunk/Source/WebCore/platform/sql/SQLiteDatabaseTracker.cpp
r243939 r244687 69 69 } 70 70 71 #if !ASSERT_DISABLED72 71 bool hasTransactionInProgress() 73 72 { … … 75 74 return !s_staticSQLiteDatabaseTrackerClient || s_transactionInProgressCounter > 0; 76 75 } 77 #endif78 76 79 77 } // namespace SQLiteDatabaseTracker -
trunk/Source/WebCore/platform/sql/SQLiteDatabaseTracker.h
r179929 r244687 38 38 WEBCORE_EXPORT void setClient(SQLiteDatabaseTrackerClient*); 39 39 40 #if !ASSERT_DISABLED41 40 WEBCORE_EXPORT bool hasTransactionInProgress(); 42 #endif43 41 44 42 }; -
trunk/Source/WebKit/ChangeLog
r244683 r244687 1 2019-04-26 Sihui Liu <sihui_liu@apple.com> 2 3 Stop IDB transactions to release locked database files when network process is ready to suspend 4 https://bugs.webkit.org/show_bug.cgi?id=196372 5 <rdar://problem/48930116> 6 7 Reviewed by Brady Eidson. 8 9 * NetworkProcess/NetworkProcess.cpp: 10 (WebKit::NetworkProcess::processWillSuspendImminently): 11 (WebKit::NetworkProcess::prepareToSuspend): 12 (WebKit::NetworkProcess::resume): 13 1 14 2019-04-25 Myles C. Maxfield <mmaxfield@apple.com> 2 15 -
trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp
r244659 r244687 2008 2008 void NetworkProcess::processWillSuspendImminently(CompletionHandler<void(bool)>&& completionHandler) 2009 2009 { 2010 #if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE) 2011 for (auto& server : m_idbServers.values()) 2012 server->tryStop(IDBServer::ShouldForceStop::Yes); 2013 #endif 2010 2014 actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::No); 2011 2015 completionHandler(true); … … 2015 2019 { 2016 2020 RELEASE_LOG(ProcessSuspension, "%p - NetworkProcess::prepareToSuspend()", this); 2021 2022 #if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE) 2023 for (auto& server : m_idbServers.values()) 2024 server->tryStop(IDBServer::ShouldForceStop::No); 2025 #endif 2017 2026 actualPrepareToSuspend(ShouldAcknowledgeWhenReadyToSuspend::Yes); 2018 2027 } … … 2053 2062 for (auto& server : m_swServers.values()) 2054 2063 server->endSuspension(); 2064 #endif 2065 #if PLATFORM(IOS_FAMILY) && ENABLE(INDEXED_DATABASE) 2066 for (auto& server : m_idbServers.values()) 2067 server->resume(); 2055 2068 #endif 2056 2069 } -
trunk/Tools/ChangeLog
r244675 r244687 1 2019-04-26 Sihui Liu <sihui_liu@apple.com> 2 3 Stop IDB transactions to release locked database files when network process is ready to suspend 4 https://bugs.webkit.org/show_bug.cgi?id=196372 5 <rdar://problem/48930116> 6 7 Reviewed by Brady Eidson. 8 9 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: 10 * TestWebKitAPI/Tests/WebKitCocoa/IndexedDBSuspendImminently.html: Added. 11 * TestWebKitAPI/Tests/WebKitCocoa/IndexedDBSuspendImminently.mm: Added. 12 (-[IndexedDBSuspendImminentlyMessageHandler userContentController:didReceiveScriptMessage:]): 13 (runTestAndCheckResult): 14 (keepNetworkProcessActive): 15 (TEST): 16 1 17 2019-04-25 Simon Fraser <simon.fraser@apple.com> 2 18 -
trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
r244644 r244687 784 784 C9E6DD351EA97D0800DD78AA /* FirstResponderSuppression.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9E6DD311EA972D800DD78AA /* FirstResponderSuppression.mm */; }; 785 785 C9E8EE7521DED94300797765 /* long-test.mp4 in Copy Resources */ = {isa = PBXBuildFile; fileRef = C9E8EE7421DED91E00797765 /* long-test.mp4 */; }; 786 CA2879DB226E69A5001026F5 /* IndexedDBSuspendImminently.mm in Sources */ = {isa = PBXBuildFile; fileRef = CA2879DA226E6986001026F5 /* IndexedDBSuspendImminently.mm */; }; 787 CA2879DC226E69B6001026F5 /* IndexedDBSuspendImminently.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CA2879D9226E6978001026F5 /* IndexedDBSuspendImminently.html */; }; 786 788 CA38459620AE17A900990D3B /* LocalStorageDatabaseTracker.mm in Sources */ = {isa = PBXBuildFile; fileRef = CA38459520AE012E00990D3B /* LocalStorageDatabaseTracker.mm */; }; 787 789 CA5B94D22190C0F40059FE38 /* IndexedDBTempFileSize-1.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CA5B94D02190C0E00059FE38 /* IndexedDBTempFileSize-1.html */; }; … … 1178 1180 57599E2A1F071AA000A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityRead.html in Copy Resources */, 1179 1181 57599E2B1F071AA000A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityWrite.html in Copy Resources */, 1182 CA2879DC226E69B6001026F5 /* IndexedDBSuspendImminently.html in Copy Resources */, 1180 1183 CA5B94D22190C0F40059FE38 /* IndexedDBTempFileSize-1.html in Copy Resources */, 1181 1184 CA5B94D32190C0F40059FE38 /* IndexedDBTempFileSize-2.html in Copy Resources */, … … 2133 2136 C9E6DD311EA972D800DD78AA /* FirstResponderSuppression.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FirstResponderSuppression.mm; sourceTree = "<group>"; }; 2134 2137 C9E8EE7421DED91E00797765 /* long-test.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "long-test.mp4"; sourceTree = "<group>"; }; 2138 CA2879D9226E6978001026F5 /* IndexedDBSuspendImminently.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = IndexedDBSuspendImminently.html; sourceTree = "<group>"; }; 2139 CA2879DA226E6986001026F5 /* IndexedDBSuspendImminently.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IndexedDBSuspendImminently.mm; sourceTree = "<group>"; }; 2135 2140 CA38459520AE012E00990D3B /* LocalStorageDatabaseTracker.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalStorageDatabaseTracker.mm; sourceTree = "<group>"; }; 2136 2141 CA5B94D02190C0E00059FE38 /* IndexedDBTempFileSize-1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "IndexedDBTempFileSize-1.html"; sourceTree = "<group>"; }; … … 2598 2603 51B1EE8D1C80F5880064FB98 /* IndexedDBPersistence.mm */, 2599 2604 57599E201F07191700A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm */, 2605 CA2879DA226E6986001026F5 /* IndexedDBSuspendImminently.mm */, 2600 2606 CA5B94D62191005B0059FE38 /* IndexedDBTempFileSize.mm */, 2601 2607 CA97B3922193663B0045DF6F /* IndexedDBUserDelete.mm */, … … 3000 3006 57599E251F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityRead.html */, 3001 3007 57599E231F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityWrite.html */, 3008 CA2879D9226E6978001026F5 /* IndexedDBSuspendImminently.html */, 3002 3009 CA5B94D02190C0E00059FE38 /* IndexedDBTempFileSize-1.html */, 3003 3010 CA5B94D12190C0E00059FE38 /* IndexedDBTempFileSize-2.html */, … … 4180 4187 7C83E0BF1D0A652200FEBCF3 /* IndexedDBPersistence.mm in Sources */, 4181 4188 57599E211F07191900A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm in Sources */, 4189 CA2879DB226E69A5001026F5 /* IndexedDBSuspendImminently.mm in Sources */, 4182 4190 CA5B94D72191005B0059FE38 /* IndexedDBTempFileSize.mm in Sources */, 4183 4191 CA97B394219366600045DF6F /* IndexedDBUserDelete.mm in Sources */,
Note: See TracChangeset
for help on using the changeset viewer.