зеркало из https://github.com/mozilla/gecko-dev.git
Bug 775676 - Fix leak in nsWebShellWindow. r=roc
After nsWebShellWindow::Destroy clears mSPTimer, it calls nsXULWindow::Destroy, which runs script. That script might cause us to call nsWebShellWindow::SetPersistenceTimer. If that happens, SetPersistenceTimer will create mSPTimer (it was nulled out during nsWebShellWindow::Destroy) and addref this. But there is no corresponding release. Let this be a lesson to all ye who try to be clever with manual addref/release!
This commit is contained in:
Родитель
645b8457bb
Коммит
2afb0a8c77
|
@ -473,28 +473,63 @@ static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class WebShellWindowTimerCallback : public nsITimerCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WebShellWindowTimerCallback(nsWebShellWindow* aWindow)
|
||||||
|
: mWindow(aWindow)
|
||||||
|
{}
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
NS_IMETHOD Notify(nsITimer* aTimer)
|
||||||
|
{
|
||||||
|
// Although this object participates in a refcount cycle (this -> mWindow
|
||||||
|
// -> mSPTimer -> this), mSPTimer is a one-shot timer and releases this
|
||||||
|
// after it fires. So we don't need to release mWindow here.
|
||||||
|
|
||||||
|
mWindow->FirePersistenceTimer();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<nsWebShellWindow> mWindow;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_THREADSAFE_ADDREF(WebShellWindowTimerCallback)
|
||||||
|
NS_IMPL_THREADSAFE_RELEASE(WebShellWindowTimerCallback)
|
||||||
|
NS_IMPL_THREADSAFE_QUERY_INTERFACE1(WebShellWindowTimerCallback,
|
||||||
|
nsITimerCallback)
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWebShellWindow::SetPersistenceTimer(PRUint32 aDirtyFlags)
|
nsWebShellWindow::SetPersistenceTimer(PRUint32 aDirtyFlags)
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mSPTimerLock);
|
MutexAutoLock lock(mSPTimerLock);
|
||||||
if (!mSPTimer) {
|
if (!mSPTimer) {
|
||||||
nsresult rv;
|
mSPTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||||
mSPTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
if (!mSPTimer) {
|
||||||
if (NS_SUCCEEDED(rv)) {
|
NS_WARNING("Couldn't create @mozilla.org/timer;1 instance?");
|
||||||
NS_ADDREF_THIS(); // for the timer, which holds a reference to this window
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mSPTimer->InitWithFuncCallback(FirePersistenceTimer, this,
|
|
||||||
SIZE_PERSISTENCE_TIMEOUT, nsITimer::TYPE_ONE_SHOT);
|
nsRefPtr<WebShellWindowTimerCallback> callback =
|
||||||
|
new WebShellWindowTimerCallback(this);
|
||||||
|
mSPTimer->InitWithCallback(callback, SIZE_PERSISTENCE_TIMEOUT,
|
||||||
|
nsITimer::TYPE_ONE_SHOT);
|
||||||
|
|
||||||
PersistentAttributesDirty(aDirtyFlags);
|
PersistentAttributesDirty(aDirtyFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWebShellWindow::FirePersistenceTimer(nsITimer *aTimer, void *aClosure)
|
nsWebShellWindow::FirePersistenceTimer()
|
||||||
{
|
{
|
||||||
nsWebShellWindow *win = static_cast<nsWebShellWindow *>(aClosure);
|
MutexAutoLock lock(mSPTimerLock);
|
||||||
MutexAutoLock lock(win->mSPTimerLock);
|
SavePersistentAttributes();
|
||||||
win->SavePersistentAttributes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -747,7 +782,6 @@ NS_IMETHODIMP nsWebShellWindow::Destroy()
|
||||||
mSPTimer->Cancel();
|
mSPTimer->Cancel();
|
||||||
SavePersistentAttributes();
|
SavePersistentAttributes();
|
||||||
mSPTimer = nsnull;
|
mSPTimer = nsnull;
|
||||||
NS_RELEASE_THIS(); // the timer held a reference to us
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nsXULWindow::Destroy();
|
return nsXULWindow::Destroy();
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
/* Forward declarations.... */
|
/* Forward declarations.... */
|
||||||
class nsIURI;
|
class nsIURI;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
class WebShellWindowTimerCallback;
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
class nsWebShellWindow : public nsXULWindow,
|
class nsWebShellWindow : public nsXULWindow,
|
||||||
public nsIWebProgressListener
|
public nsIWebProgressListener
|
||||||
{
|
{
|
||||||
|
@ -41,6 +45,7 @@ public:
|
||||||
NS_IMETHOD Destroy();
|
NS_IMETHOD Destroy();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
friend class mozilla::WebShellWindowTimerCallback;
|
||||||
|
|
||||||
virtual ~nsWebShellWindow();
|
virtual ~nsWebShellWindow();
|
||||||
|
|
||||||
|
@ -54,7 +59,7 @@ protected:
|
||||||
mozilla::Mutex mSPTimerLock;
|
mozilla::Mutex mSPTimerLock;
|
||||||
|
|
||||||
void SetPersistenceTimer(PRUint32 aDirtyFlags);
|
void SetPersistenceTimer(PRUint32 aDirtyFlags);
|
||||||
static void FirePersistenceTimer(nsITimer *aTimer, void *aClosure);
|
void FirePersistenceTimer();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче