Bug 1722803 - Always initialize TimelineConsumers at startup. r=nika

Instead of initializing on first use - which can race with workers - do the
initialization in nsLayoutStatics::Initialize(). Also make `sInShutdown` an
Atomic since it is accessed without locks.

Differential Revision: https://phabricator.services.mozilla.com/D121143
This commit is contained in:
Ted Campbell 2021-07-29 01:53:31 +00:00
parent 8b2533fa16
commit e47122deae
3 changed files with 17 additions and 30 deletions

View File

@ -32,7 +32,7 @@ StaticRefPtr<TimelineConsumers> TimelineConsumers::sInstance;
// This flag makes sure the singleton never gets instantiated while a shutdown
// is in progress. This can actually happen, and `ClearOnShutdown` doesn't work
// in these cases.
bool TimelineConsumers::sInShutdown = false;
Atomic<bool> TimelineConsumers::sInShutdown{false};
already_AddRefed<TimelineConsumers> TimelineConsumers::Get() {
// Using this class is not supported yet for other processes other than
@ -49,42 +49,26 @@ already_AddRefed<TimelineConsumers> TimelineConsumers::Get() {
return nullptr;
}
// Note: We don't simply check `sInstance` for null-ness here, since otherwise
// this can resurrect the TimelineConsumers pretty late during shutdown.
// We won't know if we're in shutdown or not though, because the singleton
// could have been destroyed or just never instantiated, so in the previous
// conditional `sInShutdown` would be false.
static bool firstTime = true;
if (firstTime) {
firstTime = false;
StaticMutexAutoLock lock(sMutex);
sInstance = new TimelineConsumers();
// Make sure the initialization actually suceeds, otherwise don't allow
// access by destroying the instance immediately.
if (sInstance->Init()) {
ClearOnShutdown(&sInstance);
} else {
sInstance->RemoveObservers();
sInstance = nullptr;
}
}
RefPtr<TimelineConsumers> copy = sInstance.get();
return copy.forget();
}
bool TimelineConsumers::Init() {
/* static */
void TimelineConsumers::Init() {
MOZ_ASSERT(!sInstance);
RefPtr<TimelineConsumers> instance = new TimelineConsumers();
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
return false;
return;
}
if (NS_WARN_IF(NS_FAILED(
obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false)))) {
return false;
obs->AddObserver(instance, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false)))) {
return;
}
return true;
sInstance = instance;
ClearOnShutdown(&sInstance);
}
bool TimelineConsumers::RemoveObservers() {

View File

@ -39,10 +39,10 @@ class TimelineConsumers : public nsIObserver {
void operator=(const TimelineConsumers& aOther) = delete;
virtual ~TimelineConsumers() = default;
bool Init();
bool RemoveObservers();
public:
static void Init();
static already_AddRefed<TimelineConsumers> Get();
// Methods for registering interested consumers (i.e. "devtools toolboxes").
@ -115,7 +115,7 @@ class TimelineConsumers : public nsIObserver {
private:
static StaticRefPtr<TimelineConsumers> sInstance;
static bool sInShutdown;
static Atomic<bool> sInShutdown;
// Counter for how many timelines are currently interested in markers,
// and a list of the MarkersStorage interfaces representing them.

View File

@ -62,6 +62,7 @@
#include "FrameLayerBuilder.h"
#include "AnimationCommon.h"
#include "LayerAnimationInfo.h"
#include "mozilla/TimelineConsumers.h"
#include "AudioChannelService.h"
#include "mozilla/dom/PromiseDebugging.h"
@ -235,6 +236,8 @@ nsresult nsLayoutStatics::Initialize() {
PointerEventHandler::InitializeStatics();
TouchManager::InitializeStatics();
TimelineConsumers::Init();
nsWindowMemoryReporter::Init();
SVGElementFactory::Init();