Bug 1749504 - Unregister invalidated directory locks when they become unblocked; r=dom-storage-reviewers,jstutte

Invalidated pending directory locks can be unregistered immediately when they
become unblocked. There's no need to wait for the last release because they
were never acquired.

Changes done in this patch:
- moved the unregistration into own Unregister method
- added the directory lock unregistration to NotifyOpenListener as well
- enabled the disabled test for ShutdownStorage

Differential Revision: https://phabricator.services.mozilla.com/D185692
This commit is contained in:
Jan Varga 2023-09-13 16:41:58 +00:00
Родитель 16b010f8fa
Коммит 8f2571576a
3 изменённых файлов: 32 добавлений и 19 удалений

Просмотреть файл

@ -52,26 +52,11 @@ DirectoryLockImpl::DirectoryLockImpl(
DirectoryLockImpl::~DirectoryLockImpl() {
AssertIsOnOwningThread();
MOZ_ASSERT_IF(!mRegistered, mBlocking.IsEmpty());
// We must call UnregisterDirectoryLock before unblocking other locks because
// UnregisterDirectoryLock also updates the origin last access time and the
// access flag (if the last lock for given origin is unregistered). One of the
// blocked locks could be requested by the clear/reset operation which stores
// cached information about origins in storage.sqlite. So if the access flag
// is not updated before unblocking the lock for reset/clear, we might store
// invalid information which can lead to omitting origin initialization during
// next temporary storage initialization.
if (mRegistered) {
mQuotaManager->UnregisterDirectoryLock(*this);
Unregister();
}
MOZ_ASSERT(!mRegistered);
for (NotNull<RefPtr<DirectoryLockImpl>> blockingLock : mBlocking) {
blockingLock->MaybeUnblock(*this);
}
mBlocking.Clear();
}
#ifdef DEBUG
@ -151,6 +136,10 @@ void DirectoryLockImpl::NotifyOpenListener() {
mQuotaManager->RemovePendingDirectoryLock(*this);
mPending.Flip();
if (mInvalidated) {
Unregister();
}
}
void DirectoryLockImpl::Invalidate() {
@ -168,6 +157,29 @@ void DirectoryLockImpl::Invalidate() {
}
}
void DirectoryLockImpl::Unregister() {
AssertIsOnOwningThread();
MOZ_ASSERT(mRegistered);
// We must call UnregisterDirectoryLock before unblocking other locks because
// UnregisterDirectoryLock also updates the origin last access time and the
// access flag (if the last lock for given origin is unregistered). One of the
// blocked locks could be requested by the clear/reset operation which stores
// cached information about origins in storage.sqlite. So if the access flag
// is not updated before unblocking the lock for reset/clear, we might store
// invalid information which can lead to omitting origin initialization during
// next temporary storage initialization.
mQuotaManager->UnregisterDirectoryLock(*this);
MOZ_ASSERT(!mRegistered);
for (NotNull<RefPtr<DirectoryLockImpl>> blockingLock : mBlocking) {
blockingLock->MaybeUnblock(*this);
}
mBlocking.Clear();
}
void DirectoryLockImpl::Acquire(RefPtr<OpenDirectoryListener> aOpenListener) {
AssertIsOnOwningThread();
MOZ_ASSERT(aOpenListener);

Просмотреть файл

@ -173,6 +173,8 @@ class DirectoryLockImpl final : public ClientDirectoryLock,
void Invalidate();
void Unregister();
// DirectoryLock interface
NS_INLINE_DECL_REFCOUNTING(DirectoryLockImpl, override)

Просмотреть файл

@ -831,8 +831,7 @@ TEST_F(TestQuotaManager, ShutdownStorage_OngoingWithScheduledInitialization) {
// because it gets invalidated while it's still pending which causes that any
// directory locks that were blocked by the shared client directory lock become
// unblocked.
TEST_F(TestQuotaManager,
DISABLED_ShutdownStorage_OngoingWithClientDirectoryLock) {
TEST_F(TestQuotaManager, ShutdownStorage_OngoingWithClientDirectoryLock) {
PerformOnBackgroundThread([]() {
QuotaManager* quotaManager = QuotaManager::Get();
ASSERT_TRUE(quotaManager);