Commit 1f6ecfc4 authored by pkasting@chromium.org's avatar pkasting@chromium.org

Bandaid a memory corruption bug by converting it to a leak.

InfoBarService doesn't delete InfoBarDelegates directly (on shutdown or at any
other time), but rather relies on a listening InfoBarContainer to delete the
corresponding InfoBars, which in turn would delete the InfoBarDelegates.

If InfoBarContainer was destroyed before InfoBarService, it could still be
holding infobars, which would then leak, because there would be no container to
do the deletions at InfoBarService destruction time.  To prevent this leak,
InfoBarContainer was calling CloseSoon() and then Hide() on all InfoBars on
destruction, which would force them to be deleted and delete their delegates.

However, this (always!) caused a write-to-freed-memory when InfoBarService shut
down, because in this case it would still be holding pointers to all the
corresponding (deleted) InfoBarDelegates, and would attempt to access them
(specifically, to call clear_owner()) when removing them.  (The clear_owner()
call is sort of a hack; really, InfoBar and InfoBarDelegate should not have
separate members pointing to the owning InfoBarService.  Unfortunately this is
necessary to avoid some other bugs in the current system.)

The core problem was that CloseSoon() tells the InfoBar it's unowned, but in
this case the InfoBar isn't actually unowned yet.  Removing the CloseSoon() call
from InfoBarContainer fixes this, at the cost of re-introducing the leak
described above.

The correct fix is for InfoBarService to talk to InfoBars instead of
InfoBarDelegates, so that regardless of the destruction order of InfoBarService
versus InfoBarContainer, InfoBars will stay alive until they're both un-owned
and hidden, then delete themselves.  In this world we also don't need
InfoBarDelegates to have a pointer back to an "owning" InfoBarService; they're
owned by long-lived InfoBars.

If this sounds familiar, that's because it's a precise description of the new
ownership model that I've written (years ago) but still not yet landed.  (Though
I'm getting close; I'm now only blocked by some Android work.)  Until this model
is landed to fix the problem correctly, we have little choice but to accept the
potential leak in this scenario.

BUG=290976
TEST=none
R=erg@chromium.org

Review URL: https://codereview.chromium.org/24151002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223405 0039d316-1c4b-4281-b951-d872f2087c98
parent d8ba27b8
......@@ -106,11 +106,6 @@ void InfoBarContainer::RemoveAllInfoBarsForDestruction() {
// this point |delegate_| may be shutting down, and it's at best unimportant
// and at worst disastrous to call that.
delegate_ = NULL;
// TODO(pkasting): Remove this once InfoBarService calls CloseSoon().
for (size_t i = infobars_.size(); i > 0; --i)
infobars_[i - 1]->CloseSoon();
ChangeInfoBarService(NULL);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment