summaryrefslogtreecommitdiffstats
path: root/webkit/appcache/appcache_group.cc
diff options
context:
space:
mode:
authormichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-30 00:03:47 +0000
committermichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-30 00:03:47 +0000
commitc472e8f245d9980be90ab9e6c6451ef5582b4d18 (patch)
treec2cf7f5ab0fcb7d175ef56fcba3eaac16243ee49 /webkit/appcache/appcache_group.cc
parent1baafb37dc6b6462a58644e4d64c543827ead8ad (diff)
downloadchromium_src-c472e8f245d9980be90ab9e6c6451ef5582b4d18.zip
chromium_src-c472e8f245d9980be90ab9e6c6451ef5582b4d18.tar.gz
chromium_src-c472e8f245d9980be90ab9e6c6451ef5582b4d18.tar.bz2
Fix a refcounting memory bug... take 2.
BUG=none TEST=existing tests apply + valgrind Review URL: http://codereview.chromium.org/552236 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37572 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache/appcache_group.cc')
-rw-r--r--webkit/appcache/appcache_group.cc21
1 files changed, 12 insertions, 9 deletions
diff --git a/webkit/appcache/appcache_group.cc b/webkit/appcache/appcache_group.cc
index e1906ab..fd22563 100644
--- a/webkit/appcache/appcache_group.cc
+++ b/webkit/appcache/appcache_group.cc
@@ -44,7 +44,8 @@ AppCacheGroup::AppCacheGroup(AppCacheService* service,
newest_complete_cache_(NULL),
update_job_(NULL),
service_(service),
- restart_update_task_(NULL) {
+ restart_update_task_(NULL),
+ is_in_dtor_(false) {
service_->storage()->working_set()->AddGroup(this);
host_observer_.reset(new HostObserver(this));
}
@@ -55,6 +56,8 @@ AppCacheGroup::~AppCacheGroup() {
DCHECK(!restart_update_task_);
DCHECK(queued_updates_.empty());
+ is_in_dtor_ = true;
+
if (update_job_)
delete update_job_;
DCHECK_EQ(IDLE, update_status_);
@@ -153,6 +156,9 @@ void AppCacheGroup::AddNewlyDeletableResponseIds(
void AppCacheGroup::StartUpdateWithNewMasterEntry(
AppCacheHost* host, const GURL& new_master_resource) {
+ if (is_in_dtor_)
+ return;
+
if (!update_job_)
update_job_ = new AppCacheUpdateJob(service_, this);
@@ -245,15 +251,12 @@ void AppCacheGroup::SetUpdateStatus(UpdateStatus status) {
} else {
update_job_ = NULL;
- // Check member variable before notifying observers about update finishing.
- // Observers may remove reference to group, causing group to be deleted
- // after the notifications. If there are queued updates, then the group
- // will continue to exist.
- bool restart_update = !queued_updates_.empty();
-
+ // Observers may release us in these callbacks, so we protect against
+ // deletion by adding an extra ref in this scope (but only if we're not
+ // in our destructor).
+ scoped_refptr<AppCacheGroup> protect(is_in_dtor_ ? NULL : this);
FOR_EACH_OBSERVER(UpdateObserver, observers_, OnUpdateComplete(this));
-
- if (restart_update)
+ if (!queued_updates_.empty())
ScheduleUpdateRestart(kUpdateRestartDelayMs);
}
}