Skip to content

Commit

Permalink
Bug 1409249: Require singleton constructors to return explicit alread…
Browse files Browse the repository at this point in the history
…y_AddRefed. r=froydnj

Right now, NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR expects singleton
constructors to return already-addrefed raw pointers, and while it accepts
constructors that return already_AddRefed, most existing don't do so.

Meanwhile, the convention elsewhere is that a raw pointer return value is
owned by the callee, and that the caller needs to addref it if it wants to
keep its own reference to it.

The difference in convention makes it easy to leak (I've definitely caused
more than one shutdown leak this way), so it would be better if we required
the singleton getters to return an explicit already_AddRefed, which would
behave the same for all callers.


This also cleans up several singleton constructors that left a dangling
pointer to their singletons when their initialization methods failed, when
they released their references without clearing their global raw pointers.

MozReview-Commit-ID: 9peyG4pRYcr
  • Loading branch information
kmaglione committed Oct 17, 2017
1 parent f0b8c3b commit a03d643
Show file tree
Hide file tree
Showing 36 changed files with 128 additions and 160 deletions.
7 changes: 3 additions & 4 deletions caps/nsScriptSecurityManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1437,13 +1437,12 @@ nsScriptSecurityManager::InitStatics()
// Currently this nsGenericFactory constructor is used only from FastLoad
// (XPCOM object deserialization) code, when "creating" the system principal
// singleton.
SystemPrincipal *
already_AddRefed<SystemPrincipal>
nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
{
nsIPrincipal *sysprin = nullptr;
if (gScriptSecMan)
NS_ADDREF(sysprin = gScriptSecMan->mSystemPrincipal);
return static_cast<SystemPrincipal*>(sysprin);
return do_AddRef(gScriptSecMan->mSystemPrincipal.get()).downcast<SystemPrincipal>();
return nullptr;
}

struct IsWhitespace {
Expand Down
2 changes: 1 addition & 1 deletion caps/nsScriptSecurityManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class nsScriptSecurityManager final : public nsIScriptSecurityManager,
// Invoked exactly once, by XPConnect.
static void InitStatics();

static SystemPrincipal*
static already_AddRefed<SystemPrincipal>
SystemPrincipalSingletonConstructor();

/**
Expand Down
8 changes: 3 additions & 5 deletions dom/base/DOMRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,10 @@ class DOMRequestService final : public nsIDOMRequestService
NS_DECL_ISUPPORTS
NS_DECL_NSIDOMREQUESTSERVICE

// Returns an owning reference! No one should call this but the factory.
static DOMRequestService* FactoryCreate()
// No one should call this but the factory.
static already_AddRefed<DOMRequestService> FactoryCreate()
{
DOMRequestService* res = new DOMRequestService;
NS_ADDREF(res);
return res;
return MakeAndAddRef<DOMRequestService>();
}
};

Expand Down
9 changes: 3 additions & 6 deletions dom/quota/QuotaManagerService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,14 +225,11 @@ QuotaManagerService::Get()
}

// static
QuotaManagerService*
already_AddRefed<QuotaManagerService>
QuotaManagerService::FactoryCreate()
{
// Returns a raw pointer that carries an owning reference! Lame, but the
// singleton factory macros force this.
QuotaManagerService* quotaManagerService = GetOrCreate();
NS_IF_ADDREF(quotaManagerService);
return quotaManagerService;
RefPtr<QuotaManagerService> quotaManagerService = GetOrCreate();
return quotaManagerService.forget();
}

void
Expand Down
4 changes: 2 additions & 2 deletions dom/quota/QuotaManagerService.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ class QuotaManagerService final
static QuotaManagerService*
Get();

// Returns an owning reference! No one should call this but the factory.
static QuotaManagerService*
// No one should call this but the factory.
static already_AddRefed<QuotaManagerService>
FactoryCreate();

void
Expand Down
17 changes: 7 additions & 10 deletions extensions/cookie/nsPermissionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -926,12 +926,11 @@ nsPermissionManager::~nsPermissionManager()
}

// static
nsIPermissionManager*
already_AddRefed<nsIPermissionManager>
nsPermissionManager::GetXPCOMSingleton()
{
if (gPermissionManager) {
NS_ADDREF(gPermissionManager);
return gPermissionManager;
return do_AddRef(gPermissionManager);
}

// Create a new singleton nsPermissionManager.
Expand All @@ -940,15 +939,13 @@ nsPermissionManager::GetXPCOMSingleton()
// Release our members, since GC cycles have already been completed and
// would result in serious leaks.
// See bug 209571.
gPermissionManager = new nsPermissionManager();
if (gPermissionManager) {
NS_ADDREF(gPermissionManager);
if (NS_FAILED(gPermissionManager->Init())) {
NS_RELEASE(gPermissionManager);
}
auto permManager = MakeRefPtr<nsPermissionManager>();
if (NS_SUCCEEDED(permManager->Init())) {
gPermissionManager = permManager.get();
return permManager.forget();
}

return gPermissionManager;
return nullptr;;
}

nsresult
Expand Down
2 changes: 1 addition & 1 deletion extensions/cookie/nsPermissionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ class nsPermissionManager final : public nsIPermissionManager,
NS_DECL_NSIOBSERVER

nsPermissionManager();
static nsIPermissionManager* GetXPCOMSingleton();
static already_AddRefed<nsIPermissionManager> GetXPCOMSingleton();
nsresult Init();

// enums for AddInternal()
Expand Down
6 changes: 2 additions & 4 deletions js/xpconnect/src/nsXPConnect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,10 @@ nsXPConnect::InitStatics()
gSelf->mRuntime->InitSingletonScopes();
}

nsXPConnect*
already_AddRefed<nsXPConnect>
nsXPConnect::GetSingleton()
{
nsXPConnect* xpc = nsXPConnect::XPConnect();
NS_IF_ADDREF(xpc);
return xpc;
return do_AddRef(nsXPConnect::XPConnect());
}

// static
Expand Down
5 changes: 1 addition & 4 deletions js/xpconnect/src/xpcprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,7 @@ class nsXPConnect final : public nsIXPConnect
return gSystemPrincipal;
}

// This returns an AddRef'd pointer. It does not do this with an 'out' param
// only because this form is required by the generic module macro:
// NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
static nsXPConnect* GetSingleton();
static already_AddRefed<nsXPConnect> GetSingleton();

// Called by module code in dll startup
static void InitStatics();
Expand Down
18 changes: 7 additions & 11 deletions modules/libjar/nsJARProtocolHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,23 +63,19 @@ NS_IMPL_ISUPPORTS(nsJARProtocolHandler,
nsIProtocolHandler,
nsISupportsWeakReference)

nsJARProtocolHandler*
already_AddRefed<nsJARProtocolHandler>
nsJARProtocolHandler::GetSingleton()
{
if (!gJarHandler) {
gJarHandler = new nsJARProtocolHandler();
if (!gJarHandler)
return nullptr;

NS_ADDREF(gJarHandler);
nsresult rv = gJarHandler->Init();
if (NS_FAILED(rv)) {
NS_RELEASE(gJarHandler);
auto jar = MakeRefPtr<nsJARProtocolHandler>();
gJarHandler = jar.get();
if (NS_FAILED(jar->Init())) {
gJarHandler = nullptr;
return nullptr;
}
return jar.forget();
}
NS_ADDREF(gJarHandler);
return gJarHandler;
return do_AddRef(gJarHandler);
}

NS_IMETHODIMP
Expand Down
2 changes: 1 addition & 1 deletion modules/libjar/nsJARProtocolHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class nsJARProtocolHandler final : public nsIJARProtocolHandler
// nsJARProtocolHandler methods:
nsJARProtocolHandler();

static nsJARProtocolHandler *GetSingleton();
static already_AddRefed<nsJARProtocolHandler> GetSingleton();

nsresult Init();

Expand Down
8 changes: 3 additions & 5 deletions modules/libpref/Preferences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3826,12 +3826,11 @@ class AddPreferencesMemoryReporterRunnable : public Runnable

} // namespace

/* static */ Preferences*
/* static */ already_AddRefed<Preferences>
Preferences::GetInstanceForService()
{
if (sPreferences) {
NS_ADDREF(sPreferences);
return sPreferences;
return do_AddRef(sPreferences);
}

if (sShutdown) {
Expand Down Expand Up @@ -3868,8 +3867,7 @@ Preferences::GetInstanceForService()
new AddPreferencesMemoryReporterRunnable();
NS_DispatchToMainThread(runnable);

NS_ADDREF(sPreferences);
return sPreferences;
return do_AddRef(sPreferences);
}

/* static */ bool
Expand Down
2 changes: 1 addition & 1 deletion modules/libpref/Preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class Preferences final
static void InitializeUserPrefs();

// Returns the singleton instance which is addreffed.
static Preferences* GetInstanceForService();
static already_AddRefed<Preferences> GetInstanceForService();

// Finallizes global members.
static void Shutdown();
Expand Down
20 changes: 8 additions & 12 deletions netwerk/base/nsIOService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,23 +351,19 @@ nsIOService::InitializeProtocolProxyService()
return rv;
}

nsIOService*
already_AddRefed<nsIOService>
nsIOService::GetInstance() {
if (!gIOService) {
gIOService = new nsIOService();
if (!gIOService)
return nullptr;
NS_ADDREF(gIOService);

nsresult rv = gIOService->Init();
if (NS_FAILED(rv)) {
NS_RELEASE(gIOService);
RefPtr<nsIOService> ios = new nsIOService();
gIOService = ios.get();
if (NS_FAILED(ios->Init())) {
gIOService = nullptr;
return nullptr;
}
return gIOService;

return ios.forget();
}
NS_ADDREF(gIOService);
return gIOService;
return do_AddRef(gIOService);
}

NS_IMPL_ISUPPORTS(nsIOService,
Expand Down
3 changes: 1 addition & 2 deletions netwerk/base/nsIOService.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ class nsIOService final : public nsIIOService2

// Gets the singleton instance of the IO Service, creating it as needed
// Returns nullptr on out of memory or failure to initialize.
// Returns an addrefed pointer.
static nsIOService* GetInstance();
static already_AddRefed<nsIOService> GetInstance();

nsresult Init();
nsresult NewURI(const char* aSpec, nsIURI* aBaseURI,
Expand Down
5 changes: 2 additions & 3 deletions netwerk/dns/ChildDNSService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,15 @@ namespace net {
static ChildDNSService *gChildDNSService;
static const char kPrefNameDisablePrefetch[] = "network.dns.disablePrefetch";

ChildDNSService* ChildDNSService::GetSingleton()
already_AddRefed<ChildDNSService> ChildDNSService::GetSingleton()
{
MOZ_ASSERT(IsNeckoChild());

if (!gChildDNSService) {
gChildDNSService = new ChildDNSService();
}

NS_ADDREF(gChildDNSService);
return gChildDNSService;
return do_AddRef(gChildDNSService);
}

NS_IMPL_ISUPPORTS(ChildDNSService,
Expand Down
2 changes: 1 addition & 1 deletion netwerk/dns/ChildDNSService.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class ChildDNSService final

ChildDNSService();

static ChildDNSService* GetSingleton();
static already_AddRefed<ChildDNSService> GetSingleton();

void NotifyRequestDone(DNSRequestChild *aDnsRequest);

Expand Down
20 changes: 9 additions & 11 deletions netwerk/dns/nsDNSService2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ NS_IMPL_ISUPPORTS(nsDNSService, nsIDNSService, nsPIDNSService, nsIObserver,
******************************************************************************/
static nsDNSService *gDNSService;

nsIDNSService*
already_AddRefed<nsIDNSService>
nsDNSService::GetXPCOMSingleton()
{
if (IsNeckoChild()) {
Expand All @@ -509,25 +509,23 @@ nsDNSService::GetXPCOMSingleton()
return GetSingleton();
}

nsDNSService*
already_AddRefed<nsDNSService>
nsDNSService::GetSingleton()
{
NS_ASSERTION(!IsNeckoChild(), "not a parent process");

if (gDNSService) {
NS_ADDREF(gDNSService);
return gDNSService;
return do_AddRef(gDNSService);
}

gDNSService = new nsDNSService();
if (gDNSService) {
NS_ADDREF(gDNSService);
if (NS_FAILED(gDNSService->Init())) {
NS_RELEASE(gDNSService);
}
auto dns = MakeRefPtr<nsDNSService>();
gDNSService = dns.get();
if (NS_FAILED(dns->Init())) {
gDNSService = nullptr;
return nullptr;
}

return gDNSService;
return dns.forget();
}

NS_IMETHODIMP
Expand Down
4 changes: 2 additions & 2 deletions netwerk/dns/nsDNSService2.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class nsDNSService final : public nsPIDNSService

nsDNSService();

static nsIDNSService* GetXPCOMSingleton();
static already_AddRefed<nsIDNSService> GetXPCOMSingleton();

size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;

Expand All @@ -51,7 +51,7 @@ class nsDNSService final : public nsPIDNSService
private:
~nsDNSService();

static nsDNSService* GetSingleton();
static already_AddRefed<nsDNSService> GetSingleton();

uint16_t GetAFForLookup(const nsACString &host, uint32_t flags);

Expand Down
5 changes: 2 additions & 3 deletions startupcache/StartupCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -700,13 +700,12 @@ StartupCacheWrapper* StartupCacheWrapper::gStartupCacheWrapper = nullptr;

NS_IMPL_ISUPPORTS(StartupCacheWrapper, nsIStartupCache)

StartupCacheWrapper* StartupCacheWrapper::GetSingleton()
already_AddRefed<StartupCacheWrapper> StartupCacheWrapper::GetSingleton()
{
if (!gStartupCacheWrapper)
gStartupCacheWrapper = new StartupCacheWrapper();

NS_ADDREF(gStartupCacheWrapper);
return gStartupCacheWrapper;
return do_AddRef(gStartupCacheWrapper);
}

nsresult
Expand Down
2 changes: 1 addition & 1 deletion startupcache/StartupCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ class StartupCacheWrapper final
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISTARTUPCACHE

static StartupCacheWrapper* GetSingleton();
static already_AddRefed<StartupCacheWrapper> GetSingleton();
static StartupCacheWrapper *gStartupCacheWrapper;
};

Expand Down
Loading

0 comments on commit a03d643

Please sign in to comment.