зеркало из https://github.com/mozilla/gecko-dev.git
Bug 911258: Part 2 - Kill the exception service. r=bsmedberg
This commit is contained in:
Родитель
4632e5911d
Коммит
af632a6a4e
|
@ -13,7 +13,6 @@ XPIDL_SOURCES += [
|
|||
'nsIDebug2.idl',
|
||||
'nsIErrorService.idl',
|
||||
'nsIException.idl',
|
||||
'nsIExceptionService.idl',
|
||||
'nsIGZFileWriter.idl',
|
||||
'nsIInterfaceRequestor.idl',
|
||||
'nsIMemory.idl',
|
||||
|
@ -95,7 +94,6 @@ CPP_SOURCES += [
|
|||
'nsDebugImpl.cpp',
|
||||
'nsErrorAsserts.cpp',
|
||||
'nsErrorService.cpp',
|
||||
'nsExceptionService.cpp',
|
||||
'nsGZFileWriter.cpp',
|
||||
'nsInterfaceRequestorAgg.cpp',
|
||||
'nsMemoryImpl.cpp',
|
||||
|
|
|
@ -1,289 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsExceptionService.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDOMException.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "pratom.h"
|
||||
#include "prthread.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
static const unsigned BAD_TLS_INDEX = (unsigned) -1;
|
||||
|
||||
#define CHECK_SERVICE_USE_OK() if (!sLock) return NS_ERROR_NOT_INITIALIZED
|
||||
#define CHECK_MANAGER_USE_OK() if (!mService || !nsExceptionService::sLock) return NS_ERROR_NOT_INITIALIZED
|
||||
|
||||
/** Exception Manager definition **/
|
||||
class nsExceptionManager MOZ_FINAL : public nsIExceptionManager
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIEXCEPTIONMANAGER
|
||||
|
||||
nsExceptionManager(nsExceptionService *svc);
|
||||
/* additional members */
|
||||
nsCOMPtr<nsIException> mCurrentException;
|
||||
nsExceptionManager *mNextThread; // not ref-counted.
|
||||
nsExceptionService *mService; // not ref-counted
|
||||
#ifdef DEBUG
|
||||
static Atomic<int32_t> totalInstances;
|
||||
#endif
|
||||
|
||||
private:
|
||||
~nsExceptionManager();
|
||||
};
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
Atomic<int32_t> nsExceptionManager::totalInstances;
|
||||
#endif
|
||||
|
||||
// Note this object is single threaded - the service itself ensures
|
||||
// one per thread.
|
||||
// An exception if the destructor, which may be called on
|
||||
// the thread shutting down xpcom
|
||||
NS_IMPL_ISUPPORTS1(nsExceptionManager, nsIExceptionManager)
|
||||
|
||||
nsExceptionManager::nsExceptionManager(nsExceptionService *svc) :
|
||||
mNextThread(nullptr),
|
||||
mService(svc)
|
||||
{
|
||||
/* member initializers and constructor code */
|
||||
#ifdef DEBUG
|
||||
++totalInstances;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsExceptionManager::~nsExceptionManager()
|
||||
{
|
||||
/* destructor code */
|
||||
#ifdef DEBUG
|
||||
--totalInstances;
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
/* void setCurrentException (in nsIException error); */
|
||||
NS_IMETHODIMP nsExceptionManager::SetCurrentException(nsIException *error)
|
||||
{
|
||||
CHECK_MANAGER_USE_OK();
|
||||
mCurrentException = error;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIException getCurrentException (); */
|
||||
NS_IMETHODIMP nsExceptionManager::GetCurrentException(nsIException **_retval)
|
||||
{
|
||||
CHECK_MANAGER_USE_OK();
|
||||
*_retval = mCurrentException;
|
||||
NS_IF_ADDREF(*_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */
|
||||
NS_IMETHODIMP nsExceptionManager::GetExceptionFromProvider(nsresult rc, nsIException * defaultException, nsIException **_retval)
|
||||
{
|
||||
CHECK_MANAGER_USE_OK();
|
||||
// Just delegate back to the service with the provider map.
|
||||
return mService->GetExceptionFromProvider(rc, defaultException, _retval);
|
||||
}
|
||||
|
||||
/* The Exception Service */
|
||||
|
||||
unsigned nsExceptionService::tlsIndex = BAD_TLS_INDEX;
|
||||
Mutex *nsExceptionService::sLock = nullptr;
|
||||
nsExceptionManager *nsExceptionService::firstThread = nullptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
Atomic<int32_t> nsExceptionService::totalInstances;
|
||||
#endif
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsExceptionService,
|
||||
nsIExceptionService,
|
||||
nsIExceptionManager,
|
||||
nsIObserver)
|
||||
|
||||
nsExceptionService::nsExceptionService()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (++totalInstances != 1) {
|
||||
NS_ERROR("The nsExceptionService is a singleton!");
|
||||
}
|
||||
#endif
|
||||
/* member initializers and constructor code */
|
||||
if (tlsIndex == BAD_TLS_INDEX) {
|
||||
DebugOnly<PRStatus> status;
|
||||
status = PR_NewThreadPrivateIndex( &tlsIndex, ThreadDestruct );
|
||||
NS_ASSERTION(status==0, "ScriptErrorService could not allocate TLS storage.");
|
||||
}
|
||||
sLock = new Mutex("nsExceptionService.sLock");
|
||||
|
||||
// observe XPCOM shutdown.
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
NS_ASSERTION(observerService, "Could not get observer service!");
|
||||
if (observerService)
|
||||
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
}
|
||||
|
||||
nsExceptionService::~nsExceptionService()
|
||||
{
|
||||
Shutdown();
|
||||
/* destructor code */
|
||||
#ifdef DEBUG
|
||||
--totalInstances;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void nsExceptionService::ThreadDestruct( void *data )
|
||||
{
|
||||
if (!sLock) {
|
||||
NS_WARNING("nsExceptionService ignoring thread destruction after shutdown");
|
||||
return;
|
||||
}
|
||||
DropThread( (nsExceptionManager *)data );
|
||||
}
|
||||
|
||||
|
||||
void nsExceptionService::Shutdown()
|
||||
{
|
||||
if (sLock) {
|
||||
DropAllThreads();
|
||||
delete sLock;
|
||||
sLock = nullptr;
|
||||
}
|
||||
PR_SetThreadPrivate(tlsIndex, nullptr);
|
||||
}
|
||||
|
||||
/* void setCurrentException (in nsIException error); */
|
||||
NS_IMETHODIMP nsExceptionService::SetCurrentException(nsIException *error)
|
||||
{
|
||||
CHECK_SERVICE_USE_OK();
|
||||
nsCOMPtr<nsIExceptionManager> sm;
|
||||
nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm));
|
||||
if (NS_FAILED(nr))
|
||||
return nr;
|
||||
return sm->SetCurrentException(error);
|
||||
}
|
||||
|
||||
/* nsIException getCurrentException (); */
|
||||
NS_IMETHODIMP nsExceptionService::GetCurrentException(nsIException **_retval)
|
||||
{
|
||||
CHECK_SERVICE_USE_OK();
|
||||
nsCOMPtr<nsIExceptionManager> sm;
|
||||
nsresult nr = GetCurrentExceptionManager(getter_AddRefs(sm));
|
||||
if (NS_FAILED(nr))
|
||||
return nr;
|
||||
return sm->GetCurrentException(_retval);
|
||||
}
|
||||
|
||||
/* nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException); */
|
||||
NS_IMETHODIMP nsExceptionService::GetExceptionFromProvider(nsresult rc,
|
||||
nsIException * defaultException, nsIException **_retval)
|
||||
{
|
||||
CHECK_SERVICE_USE_OK();
|
||||
return DoGetExceptionFromProvider(rc, defaultException, _retval);
|
||||
}
|
||||
|
||||
/* readonly attribute nsIExceptionManager currentExceptionManager; */
|
||||
NS_IMETHODIMP nsExceptionService::GetCurrentExceptionManager(nsIExceptionManager * *aCurrentScriptManager)
|
||||
{
|
||||
CHECK_SERVICE_USE_OK();
|
||||
nsExceptionManager *mgr = (nsExceptionManager *)PR_GetThreadPrivate(tlsIndex);
|
||||
if (mgr == nullptr) {
|
||||
// Stick the new exception object in with no reference count.
|
||||
mgr = new nsExceptionManager(this);
|
||||
PR_SetThreadPrivate(tlsIndex, mgr);
|
||||
// The reference count is held in the thread-list
|
||||
AddThread(mgr);
|
||||
}
|
||||
*aCurrentScriptManager = mgr;
|
||||
NS_ADDREF(*aCurrentScriptManager);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIObserver
|
||||
NS_IMETHODIMP nsExceptionService::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
|
||||
{
|
||||
Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsExceptionService::DoGetExceptionFromProvider(nsresult errCode,
|
||||
nsIException * defaultException,
|
||||
nsIException **_exc)
|
||||
{
|
||||
// Check for an existing exception
|
||||
nsresult nr = GetCurrentException(_exc);
|
||||
if (NS_SUCCEEDED(nr) && *_exc) {
|
||||
(*_exc)->GetResult(&nr);
|
||||
// If it matches our result then use it
|
||||
if (nr == errCode)
|
||||
return NS_OK;
|
||||
NS_RELEASE(*_exc);
|
||||
}
|
||||
|
||||
switch (NS_ERROR_GET_MODULE(errCode)) {
|
||||
case NS_ERROR_MODULE_DOM:
|
||||
case NS_ERROR_MODULE_SVG:
|
||||
case NS_ERROR_MODULE_DOM_XPATH:
|
||||
case NS_ERROR_MODULE_DOM_INDEXEDDB:
|
||||
case NS_ERROR_MODULE_DOM_FILEHANDLE:
|
||||
if (NS_IsMainThread()) {
|
||||
return NS_NewDOMException(errCode, defaultException, _exc);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// No provider so we'll return the default exception
|
||||
*_exc = defaultException;
|
||||
NS_IF_ADDREF(*_exc);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// thread management
|
||||
/*static*/ void nsExceptionService::AddThread(nsExceptionManager *thread)
|
||||
{
|
||||
MutexAutoLock lock(*sLock);
|
||||
thread->mNextThread = firstThread;
|
||||
firstThread = thread;
|
||||
NS_ADDREF(thread);
|
||||
}
|
||||
|
||||
/*static*/ void nsExceptionService::DoDropThread(nsExceptionManager *thread)
|
||||
{
|
||||
nsExceptionManager **emp = &firstThread;
|
||||
while (*emp != thread) {
|
||||
NS_ABORT_IF_FALSE(*emp, "Could not find the thread to drop!");
|
||||
emp = &(*emp)->mNextThread;
|
||||
}
|
||||
*emp = thread->mNextThread;
|
||||
NS_RELEASE(thread);
|
||||
}
|
||||
|
||||
/*static*/ void nsExceptionService::DropThread(nsExceptionManager *thread)
|
||||
{
|
||||
MutexAutoLock lock(*sLock);
|
||||
DoDropThread(thread);
|
||||
}
|
||||
|
||||
/*static*/ void nsExceptionService::DropAllThreads()
|
||||
{
|
||||
MutexAutoLock lock(*sLock);
|
||||
while (firstThread)
|
||||
DoDropThread(firstThread);
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsExceptionService_h__
|
||||
#define nsExceptionService_h__
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
#include "nsIException.h"
|
||||
#include "nsIExceptionService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class nsExceptionManager;
|
||||
|
||||
/** Exception Service definition **/
|
||||
class nsExceptionService MOZ_FINAL : public nsIExceptionService, public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIEXCEPTIONSERVICE
|
||||
NS_DECL_NSIEXCEPTIONMANAGER
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
nsExceptionService();
|
||||
|
||||
/* additional members */
|
||||
nsresult DoGetExceptionFromProvider(nsresult errCode,
|
||||
nsIException *defaultException,
|
||||
nsIException **_richError);
|
||||
void Shutdown();
|
||||
|
||||
|
||||
/* thread management and cleanup */
|
||||
static void AddThread(nsExceptionManager *);
|
||||
static void DropThread(nsExceptionManager *);
|
||||
static void DoDropThread(nsExceptionManager *thread);
|
||||
|
||||
static void DropAllThreads();
|
||||
static nsExceptionManager *firstThread;
|
||||
|
||||
/* Protects the thread list. */
|
||||
static mozilla::Mutex* sLock;
|
||||
|
||||
static unsigned tlsIndex;
|
||||
static void ThreadDestruct( void *data );
|
||||
#ifdef DEBUG
|
||||
static mozilla::Atomic<int32_t> totalInstances;
|
||||
#endif
|
||||
|
||||
private:
|
||||
~nsExceptionService();
|
||||
};
|
||||
|
||||
|
||||
#endif // nsExceptionService_h__
|
|
@ -1,42 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsIException.idl"
|
||||
|
||||
// A ScriptErrorManager for a single thread. These objects
|
||||
// are _not_ thread-safe. Use the ScriptErrorService
|
||||
// to get a script error manager for your current thread.
|
||||
[scriptable, uuid(efc9d00b-231c-4feb-852c-ac017266a415)]
|
||||
interface nsIExceptionManager : nsISupports
|
||||
{
|
||||
/** Sets (or clears with nullptr) the current error on the this thread. */
|
||||
void setCurrentException( in nsIException error);
|
||||
|
||||
/** Gets the current error for the current thread, or NULL if no error */
|
||||
nsIException getCurrentException();
|
||||
|
||||
/** Gets an exception from a registered exception provider..
|
||||
This has no effect on the "current exception" */
|
||||
nsIException getExceptionFromProvider( in nsresult rc, in nsIException defaultException);
|
||||
};
|
||||
|
||||
|
||||
// The Exception Service. Allows you to get an set exceptions in a thread
|
||||
// safe manner, or to get an ExceptionManager for your specific thread.
|
||||
[scriptable, uuid(8f9ccabb-a68b-43e3-b570-dd8c3179d2fb)]
|
||||
interface nsIExceptionService : nsIExceptionManager
|
||||
{
|
||||
/** Obtains an exception manager for the current thread. */
|
||||
readonly attribute nsIExceptionManager currentExceptionManager;
|
||||
};
|
||||
|
||||
|
||||
%{ C++
|
||||
// {35A88F54-F267-4414-92A7-191F6454AB52}
|
||||
#define NS_EXCEPTIONSERVICE_CID \
|
||||
{ 0x35a88f54, 0xf267, 0x4414, { 0x92, 0xa7, 0x19, 0x1f, 0x64, 0x54, 0xab, 0x52 } }
|
||||
#define NS_EXCEPTIONSERVICE_CONTRACTID "@mozilla.org/exceptionservice;1"
|
||||
%}
|
|
@ -73,7 +73,6 @@
|
|||
#include "nsIErrorService.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIException.h"
|
||||
#include "nsIExceptionService.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIHashable.h"
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
COMPONENT(SUPPORTSARRAY, nsSupportsArray::Create)
|
||||
COMPONENT(ARRAY, nsArray::XPCOMConstructor)
|
||||
COMPONENT(CONSOLESERVICE, nsConsoleServiceConstructor)
|
||||
COMPONENT(EXCEPTIONSERVICE, nsExceptionServiceConstructor)
|
||||
COMPONENT(ATOMSERVICE, nsAtomServiceConstructor)
|
||||
COMPONENT(OBSERVERSERVICE, nsObserverService::Create)
|
||||
#ifdef MOZ_VISUAL_EVENT_TRACER
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
#include "nsINIParserImpl.h"
|
||||
#include "nsSupportsPrimitives.h"
|
||||
#include "nsConsoleService.h"
|
||||
#include "nsExceptionService.h"
|
||||
|
||||
#include "nsComponentManager.h"
|
||||
#include "nsCategoryManagerUtils.h"
|
||||
|
@ -181,7 +180,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSupportsInterfacePointerImpl)
|
|||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsConsoleService, Init)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAtomService)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsExceptionService)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimerImpl)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryOutputStream)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBinaryInputStream)
|
||||
|
|
Загрузка…
Ссылка в новой задаче