Bug 1379763 - Part 2: Avoid leaking the bhr-thread-hang runnable when shutting down, r=smaug

Unfortunately during shutdown we can sometimes leak the runnable passed into
SystemGroup::Dispatch. It is leaked instead of being freed off main thread
because we sometimes are passing data which can only be freed on the main thread
safely to the main thread, and running the destructor on the wrong thread could
be really bad.

This is a really really gross workaround for that issue which helps to avoid the
XPCOM leak checker failures which were appearing on try.

MozReview-Commit-ID: GTfdxKnsTae
This commit is contained in:
Michael Layzell 2017-07-12 12:48:51 -04:00
Родитель 4abca6951d
Коммит 2321f62b21
1 изменённых файлов: 22 добавлений и 3 удалений

Просмотреть файл

@ -622,15 +622,34 @@ BackgroundHangThread::ReportHang(PRIntervalTime aHangTime)
// Notify any observers of the "bhr-thread-hang" topic that a thread has hung.
nsCString name;
name.AssignASCII(mStats.GetName());
SystemGroup::Dispatch("NotifyBHRHangObservers", TaskCategory::Other,
NS_NewRunnableFunction("NotifyBHRHangObservers", [=] {
nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction("NotifyBHRHangObservers", [=] {
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
// NOTE: Make sure to construct this on the main thread.
nsCOMPtr<nsIHangDetails> hangDetails = new HangDetails(aHangTime, name);
os->NotifyObservers(hangDetails, "bhr-thread-hang", nullptr);
}
}));
});
if (SystemGroup::Initialized()) {
// XXX(HACK): This is really sketchy. We need to keep a reference to the
// runnable in case the dispatch fails. If it fails, the already_AddRefed
// runnable which we passed in has been leaked, and we need to free it
// ourselves. The only time when this should fail is if we're shutting down.
//
// Most components just avoid dispatching runnables during shutdown, but BHR
// is not shut down until way too late, so we cannot do that. Instead, we
// just detect that the dispatch failed and manually unleak the leaked
// nsIRunnable in that situation.
nsresult rv = SystemGroup::Dispatch("NotifyBHRHangObservers",
TaskCategory::Other,
do_AddRef(runnable.get()));
if (NS_FAILED(rv)) {
// NOTE: We go through `get()` here in order to avoid the
// MOZ_NO_ADDREF_RELEASE_ON_RETURN static analysis.
nsrefcnt refcnt = runnable.get()->Release();
MOZ_RELEASE_ASSERT(refcnt == 1, "runnable should have had 1 reference leaked");
}
}
// Process the hang off-main thread. We record a reference to the runnable in
// mProcessHangRunnables so we can abort this preprocessing and just submit