Bug 1863129 - Discard pending file deletions on shutdown but block shutdown for running deletions. r=dom-storage-reviewers,janv

In case we did start a DeleteFilesRunnable before shutdown we should ensure it is going to be executed before we leave our QM shutdown barrier, but we can ignore pending but not yet started deletions completely as PBM origins are deleted entirely by other means.

Differential Revision: https://phabricator.services.mozilla.com/D203502
This commit is contained in:
Jens Stutte 2024-03-18 13:57:53 +00:00
parent 4a3879326e
commit 691c04b46a

View File

@ -122,6 +122,7 @@
#include "mozilla/dom/quota/CheckedUnsafePtr.h"
#include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/ClientImpl.h"
#include "mozilla/dom/quota/DebugOnlyMacro.h"
#include "mozilla/dom/quota/DirectoryLock.h"
#include "mozilla/dom/quota/DecryptingInputStream_impl.h"
#include "mozilla/dom/quota/EncryptingOutputStream_impl.h"
@ -4866,6 +4867,9 @@ class DeleteFilesRunnable final : public Runnable {
RefPtr<DirectoryLock> mDirectoryLock;
nsTArray<int64_t> mFileIds;
State mState;
DEBUGONLY(bool mDEBUGCountsAsPending = false);
static uint64_t sPendingRunnables;
public:
DeleteFilesRunnable(SafeRefPtr<DatabaseFileManager> aFileManager,
@ -4873,8 +4877,14 @@ class DeleteFilesRunnable final : public Runnable {
void RunImmediately();
static bool IsDeletionPending() { return sPendingRunnables > 0; }
private:
#ifdef DEBUG
~DeleteFilesRunnable();
#else
~DeleteFilesRunnable() = default;
#endif
void Open();
@ -12488,6 +12498,17 @@ void QuotaClient::StopIdleMaintenance() {
void QuotaClient::InitiateShutdown() {
AssertIsOnBackgroundThread();
MOZ_ASSERT(IsShuttingDownOnBackgroundThread());
if (mDeleteTimer) {
// QuotaClient::AsyncDeleteFile will not schedule new timers beyond
// shutdown. And we expect all critical (PBM) deletions to have been
// triggered before this point via ClearPrivateRepository (w/out using
// DeleteFilesRunnable at all).
mDeleteTimer->Cancel();
mDeleteTimer = nullptr;
mPendingDeleteInfos.Clear();
}
AbortAllOperations();
}
@ -12495,7 +12516,7 @@ void QuotaClient::InitiateShutdown() {
bool QuotaClient::IsShutdownCompleted() const {
return (!gFactoryOps || gFactoryOps->IsEmpty()) &&
(!gLiveDatabaseHashtable || !gLiveDatabaseHashtable->Count()) &&
!mCurrentMaintenance;
!mCurrentMaintenance && !DeleteFilesRunnable::IsDeletionPending();
}
void QuotaClient::ForceKillActors() {
@ -12575,17 +12596,20 @@ void QuotaClient::FinalizeShutdown() {
mMaintenanceThreadPool->Shutdown();
mMaintenanceThreadPool = nullptr;
}
if (mDeleteTimer) {
MOZ_ALWAYS_SUCCEEDS(mDeleteTimer->Cancel());
mDeleteTimer = nullptr;
}
}
void QuotaClient::DeleteTimerCallback(nsITimer* aTimer, void* aClosure) {
AssertIsOnBackgroundThread();
MOZ_ASSERT(aTimer);
// Even though we do not schedule new timers after shutdown has started,
// an already existing one might fire afterwards (actually we think it
// shouldn't, but there is no reason to enforce this invariant). We can
// just ignore it, the cleanup work is done in InitiateShutdown.
if (NS_WARN_IF(IsShuttingDownOnBackgroundThread())) {
return;
}
auto* const self = static_cast<QuotaClient*>(aClosure);
MOZ_ASSERT(self);
MOZ_ASSERT(self->mDeleteTimer);
@ -12728,6 +12752,8 @@ void QuotaClient::ProcessMaintenanceQueue() {
* DeleteFilesRunnable
******************************************************************************/
uint64_t DeleteFilesRunnable::sPendingRunnables = 0;
DeleteFilesRunnable::DeleteFilesRunnable(
SafeRefPtr<DatabaseFileManager> aFileManager, nsTArray<int64_t>&& aFileIds)
: Runnable("dom::indexeddb::DeleteFilesRunnable"),
@ -12736,6 +12762,12 @@ DeleteFilesRunnable::DeleteFilesRunnable(
mFileIds(std::move(aFileIds)),
mState(State_Initial) {}
#ifdef DEBUG
DeleteFilesRunnable::~DeleteFilesRunnable() {
MOZ_ASSERT(!mDEBUGCountsAsPending);
}
#endif
void DeleteFilesRunnable::RunImmediately() {
AssertIsOnBackgroundThread();
MOZ_ASSERT(mState == State_Initial);
@ -12747,6 +12779,10 @@ void DeleteFilesRunnable::Open() {
AssertIsOnBackgroundThread();
MOZ_ASSERT(mState == State_Initial);
MOZ_ASSERT(!mDEBUGCountsAsPending);
sPendingRunnables++;
DEBUGONLY(mDEBUGCountsAsPending = true);
QuotaManager* const quotaManager = QuotaManager::Get();
if (NS_WARN_IF(!quotaManager)) {
Finish();
@ -12800,6 +12836,9 @@ void DeleteFilesRunnable::UnblockOpen() {
MOZ_ASSERT(mState == State_UnblockingOpen);
mDirectoryLock = nullptr;
MOZ_ASSERT(mDEBUGCountsAsPending);
sPendingRunnables--;
DEBUGONLY(mDEBUGCountsAsPending = false);
mState = State_Completed;
}