Bug 1212333 - WorkerDebuggerManager should live on the main thread;r=khuey

This commit is contained in:
Eddy Bruel 2016-02-10 10:45:02 +01:00
parent 909c7f0f0d
commit 9f155b760b
4 changed files with 132 additions and 58 deletions

View File

@ -1974,12 +1974,6 @@ RuntimeService::Shutdown()
// That's it, no more workers.
mShuttingDown = true;
// Remove all listeners from the worker debugger manager to ensure that it
// gets properly destroyed.
if (NS_FAILED(ClearWorkerDebuggerManagerListeners())) {
NS_WARNING("Failed to clear worker debugger manager listeners!");
}
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_WARN_IF_FALSE(obs, "Failed to get observer service?!");

View File

@ -8,22 +8,23 @@
#include "nsISimpleEnumerator.h"
#include "mozilla/ClearOnShutdown.h"
#include "WorkerPrivate.h"
USING_WORKERS_NAMESPACE
namespace {
class RegisterDebuggerMainThreadRunnable final : public nsRunnable
{
RefPtr<WorkerDebuggerManager> mManager;
WorkerPrivate* mWorkerPrivate;
bool mNotifyListeners;
public:
RegisterDebuggerMainThreadRunnable(WorkerDebuggerManager* aManager,
WorkerPrivate* aWorkerPrivate,
RegisterDebuggerMainThreadRunnable(WorkerPrivate* aWorkerPrivate,
bool aNotifyListeners)
: mManager(aManager),
mWorkerPrivate(aWorkerPrivate),
: mWorkerPrivate(aWorkerPrivate),
mNotifyListeners(aNotifyListeners)
{ }
@ -34,21 +35,21 @@ private:
NS_IMETHOD
Run() override
{
mManager->RegisterDebuggerMainThread(mWorkerPrivate, mNotifyListeners);
WorkerDebuggerManager* manager = WorkerDebuggerManager::Get();
MOZ_ASSERT(manager);
manager->RegisterDebuggerMainThread(mWorkerPrivate, mNotifyListeners);
return NS_OK;
}
};
class UnregisterDebuggerMainThreadRunnable final : public nsRunnable
{
RefPtr<WorkerDebuggerManager> mManager;
WorkerPrivate* mWorkerPrivate;
public:
UnregisterDebuggerMainThreadRunnable(WorkerDebuggerManager* aManager,
WorkerPrivate* aWorkerPrivate)
: mManager(aManager), mWorkerPrivate(aWorkerPrivate)
explicit UnregisterDebuggerMainThreadRunnable(WorkerPrivate* aWorkerPrivate)
: mWorkerPrivate(aWorkerPrivate)
{ }
private:
@ -58,12 +59,19 @@ private:
NS_IMETHOD
Run() override
{
mManager->UnregisterDebuggerMainThread(mWorkerPrivate);
WorkerDebuggerManager* manager = WorkerDebuggerManager::Get();
MOZ_ASSERT(manager);
manager->UnregisterDebuggerMainThread(mWorkerPrivate);
return NS_OK;
}
};
// Does not hold an owning reference.
static WorkerDebuggerManager* gWorkerDebuggerManager;
} /* anonymous namespace */
BEGIN_WORKERS_NAMESPACE
class WorkerDebuggerEnumerator final : public nsISimpleEnumerator
@ -116,7 +124,54 @@ WorkerDebuggerManager::~WorkerDebuggerManager()
AssertIsOnMainThread();
}
NS_IMPL_ISUPPORTS(WorkerDebuggerManager, nsIWorkerDebuggerManager);
// static
already_AddRefed<WorkerDebuggerManager>
WorkerDebuggerManager::GetInstance()
{
RefPtr<WorkerDebuggerManager> manager = WorkerDebuggerManager::GetOrCreate();
return manager.forget();
}
// static
WorkerDebuggerManager*
WorkerDebuggerManager::GetOrCreate()
{
AssertIsOnMainThread();
if (!gWorkerDebuggerManager) {
// The observer service now owns us until shutdown.
gWorkerDebuggerManager = new WorkerDebuggerManager();
if (NS_FAILED(gWorkerDebuggerManager->Init())) {
NS_WARNING("Failed to initialize worker debugger manager!");
gWorkerDebuggerManager = nullptr;
return nullptr;
}
}
return gWorkerDebuggerManager;
}
WorkerDebuggerManager*
WorkerDebuggerManager::Get()
{
MOZ_ASSERT(gWorkerDebuggerManager);
return gWorkerDebuggerManager;
}
NS_IMPL_ISUPPORTS(WorkerDebuggerManager, nsIObserver, nsIWorkerDebuggerManager);
NS_IMETHODIMP
WorkerDebuggerManager::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
Shutdown();
return NS_OK;
}
NS_NOTREACHED("Unknown observer topic!");
return NS_OK;
}
NS_IMETHODIMP
WorkerDebuggerManager::GetWorkerDebuggerEnumerator(
@ -161,8 +216,20 @@ WorkerDebuggerManager::RemoveListener(
return NS_OK;
}
nsresult
WorkerDebuggerManager::Init()
{
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
nsresult rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
void
WorkerDebuggerManager::ClearListeners()
WorkerDebuggerManager::Shutdown()
{
AssertIsOnMainThread();
@ -205,8 +272,7 @@ WorkerDebuggerManager::RegisterDebugger(WorkerPrivate* aWorkerPrivate)
}
nsCOMPtr<nsIRunnable> runnable =
new RegisterDebuggerMainThreadRunnable(this, aWorkerPrivate,
hasListeners);
new RegisterDebuggerMainThreadRunnable(aWorkerPrivate, hasListeners);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));
@ -225,7 +291,7 @@ WorkerDebuggerManager::UnregisterDebugger(WorkerPrivate* aWorkerPrivate)
UnregisterDebuggerMainThread(aWorkerPrivate);
} else {
nsCOMPtr<nsIRunnable> runnable =
new UnregisterDebuggerMainThreadRunnable(this, aWorkerPrivate);
new UnregisterDebuggerMainThreadRunnable(aWorkerPrivate);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL)));

View File

@ -9,6 +9,7 @@
#include "Workers.h"
#include "nsIObserver.h"
#include "nsIWorkerDebuggerManager.h"
#include "nsServiceManagerUtils.h"
@ -24,7 +25,8 @@ BEGIN_WORKERS_NAMESPACE
class WorkerDebugger;
class WorkerDebuggerManager final : public nsIWorkerDebuggerManager
class WorkerDebuggerManager final : public nsIObserver,
public nsIWorkerDebuggerManager
{
Mutex mMutex;
@ -35,54 +37,58 @@ class WorkerDebuggerManager final : public nsIWorkerDebuggerManager
nsTArray<RefPtr<WorkerDebugger>> mDebuggers;
public:
static already_AddRefed<WorkerDebuggerManager>
GetInstance();
static WorkerDebuggerManager*
GetOrCreateService()
{
nsCOMPtr<nsIWorkerDebuggerManager> manager =
do_GetService(WORKERDEBUGGERMANAGER_CONTRACTID);
return static_cast<WorkerDebuggerManager*>(manager.get());
}
GetOrCreate();
static WorkerDebuggerManager*
Get();
WorkerDebuggerManager();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSIWORKERDEBUGGERMANAGER
void ClearListeners();
nsresult
Init();
void RegisterDebugger(WorkerPrivate* aWorkerPrivate);
void
Shutdown();
void UnregisterDebugger(WorkerPrivate* aWorkerPrivate);
void
RegisterDebugger(WorkerPrivate* aWorkerPrivate);
void RegisterDebuggerMainThread(WorkerPrivate* aWorkerPrivate,
bool aNotifyListeners);
void
RegisterDebuggerMainThread(WorkerPrivate* aWorkerPrivate,
bool aNotifyListeners);
void UnregisterDebuggerMainThread(WorkerPrivate* aWorkerPrivate);
void
UnregisterDebugger(WorkerPrivate* aWorkerPrivate);
void
UnregisterDebuggerMainThread(WorkerPrivate* aWorkerPrivate);
private:
virtual ~WorkerDebuggerManager();
};
inline nsresult
ClearWorkerDebuggerManagerListeners()
{
RefPtr<WorkerDebuggerManager> manager =
WorkerDebuggerManager::GetOrCreateService();
if (!manager) {
return NS_ERROR_FAILURE;
}
manager->ClearListeners();
return NS_OK;
}
inline nsresult
RegisterWorkerDebugger(WorkerPrivate* aWorkerPrivate)
{
RefPtr<WorkerDebuggerManager> manager =
WorkerDebuggerManager::GetOrCreateService();
if (!manager) {
return NS_ERROR_FAILURE;
WorkerDebuggerManager* manager;
if (NS_IsMainThread()) {
manager = WorkerDebuggerManager::GetOrCreate();
if (!manager) {
NS_WARNING("Failed to create worker debugger manager!");
return NS_ERROR_FAILURE;
}
}
else {
manager = WorkerDebuggerManager::Get();
}
manager->RegisterDebugger(aWorkerPrivate);
@ -92,10 +98,17 @@ RegisterWorkerDebugger(WorkerPrivate* aWorkerPrivate)
inline nsresult
UnregisterWorkerDebugger(WorkerPrivate* aWorkerPrivate)
{
RefPtr<WorkerDebuggerManager> manager =
WorkerDebuggerManager::GetOrCreateService();
if (!manager) {
return NS_ERROR_FAILURE;
WorkerDebuggerManager* manager;
if (NS_IsMainThread()) {
manager = WorkerDebuggerManager::GetOrCreate();
if (!manager) {
NS_WARNING("Failed to create worker debugger manager!");
return NS_ERROR_FAILURE;
}
}
else {
manager = WorkerDebuggerManager::Get();
}
manager->UnregisterDebugger(aWorkerPrivate);

View File

@ -322,7 +322,8 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(QuotaManagerService,
QuotaManagerService::FactoryCreate)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ServiceWorkerManager,
ServiceWorkerManager::GetInstance)
NS_GENERIC_FACTORY_CONSTRUCTOR(WorkerDebuggerManager)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WorkerDebuggerManager,
WorkerDebuggerManager::GetInstance)
#ifdef MOZ_WIDGET_GONK
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(SystemWorkerManager,