Commit 57a48d36 authored by szym@chromium.org's avatar szym@chromium.org

[net] Ensure aborted HostResolverImpl::Jobs release slots in the dispatcher.

Also re-introduces a missing life check in case a request callback deletes the HostResolver.

R=eroman@chromium.org,cbentzel@chromium.org
BUG=115399
TEST=./net_unittest --gtest_filter=HostResolverImplTest.CanceledRequestsReleaseJobSlots


Review URL: http://codereview.chromium.org/9572018

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@124783 0039d316-1c4b-4281-b951-d872f2087c98
parent 1f873033
...@@ -1076,8 +1076,6 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { ...@@ -1076,8 +1076,6 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
make_scoped_refptr(new JobCreationParameters( make_scoped_refptr(new JobCreationParameters(
key_.hostname, request_net_log.source()))); key_.hostname, request_net_log.source())));
handle_ = resolver_->dispatcher_.Add(this, priority);
} }
virtual ~Job() { virtual ~Job() {
...@@ -1091,7 +1089,7 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { ...@@ -1091,7 +1089,7 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB,
ERR_ABORTED); ERR_ABORTED);
} else if (is_queued()) { } else if (is_queued()) {
// This Job was cancelled without running. // |resolver_| was destroyed without running this Job.
// TODO(szym): is there's any benefit in having this distinction? // TODO(szym): is there's any benefit in having this distinction?
net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL); net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, NULL); net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, NULL);
...@@ -1111,6 +1109,10 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { ...@@ -1111,6 +1109,10 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
STLDeleteElements(&requests_); STLDeleteElements(&requests_);
} }
void Schedule() {
handle_ = resolver_->dispatcher_.Add(this, priority());
}
RequestPriority priority() const { RequestPriority priority() const {
return priority_tracker_.highest_priority(); return priority_tracker_.highest_priority();
} }
...@@ -1176,6 +1178,8 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job { ...@@ -1176,6 +1178,8 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job {
} else { } else {
resolver_->dispatcher_.Cancel(handle_); resolver_->dispatcher_.Cancel(handle_);
handle_.Reset(); handle_.Reset();
net_log_.AddEvent(NetLog::TYPE_CANCELLED, NULL);
net_log_.EndEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_JOB, NULL);
} }
} }
} }
...@@ -1487,6 +1491,7 @@ int HostResolverImpl::Resolve(const RequestInfo& info, ...@@ -1487,6 +1491,7 @@ int HostResolverImpl::Resolve(const RequestInfo& info,
if (jobit == jobs_.end()) { if (jobit == jobs_.end()) {
// Create new Job. // Create new Job.
job = new Job(this, key, request_net_log, info.priority()); job = new Job(this, key, request_net_log, info.priority());
job->Schedule();
// Check for queue overflow. // Check for queue overflow.
if (dispatcher_.num_queued_jobs() > max_queued_jobs_) { if (dispatcher_.num_queued_jobs() > max_queued_jobs_) {
...@@ -1572,8 +1577,10 @@ void HostResolverImpl::CancelRequest(RequestHandle req_handle) { ...@@ -1572,8 +1577,10 @@ void HostResolverImpl::CancelRequest(RequestHandle req_handle) {
// that Request could not have been cancelled, so job->num_active_requests() // that Request could not have been cancelled, so job->num_active_requests()
// could not be 0. Therefore, we are not in Job::CompleteRequests(). // could not be 0. Therefore, we are not in Job::CompleteRequests().
RemoveJob(job); RemoveJob(job);
if (job->is_running()) if (job->is_running()) {
dispatcher_.OnJobFinished();
job->Abort(); job->Abort();
}
delete job; delete job;
} }
} }
...@@ -1709,7 +1716,6 @@ HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest( ...@@ -1709,7 +1716,6 @@ HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest(
} }
void HostResolverImpl::AbortAllInProgressJobs() { void HostResolverImpl::AbortAllInProgressJobs() {
base::WeakPtr<HostResolverImpl> self = AsWeakPtr();
// In Abort, a Request callback could spawn new Jobs with matching keys, so // In Abort, a Request callback could spawn new Jobs with matching keys, so
// first collect and remove all running jobs from |jobs_|. // first collect and remove all running jobs from |jobs_|.
std::vector<Job*> jobs_to_abort; std::vector<Job*> jobs_to_abort;
...@@ -1724,10 +1730,16 @@ void HostResolverImpl::AbortAllInProgressJobs() { ...@@ -1724,10 +1730,16 @@ void HostResolverImpl::AbortAllInProgressJobs() {
} }
} }
// Check if no dispatcher slots leaked out.
DCHECK_EQ(dispatcher_.num_running_jobs(), jobs_to_abort.size());
// Life check to bail once |this| is deleted.
base::WeakPtr<HostResolverImpl> self = AsWeakPtr();
// Then Abort them and dispatch new Jobs. // Then Abort them and dispatch new Jobs.
for (size_t i = 0; i < jobs_to_abort.size(); ++i) { for (size_t i = 0; self && i < jobs_to_abort.size(); ++i) {
jobs_to_abort[i]->Abort();
dispatcher_.OnJobFinished(); dispatcher_.OnJobFinished();
jobs_to_abort[i]->Abort();
} }
STLDeleteElements(&jobs_to_abort); STLDeleteElements(&jobs_to_abort);
} }
......
This diff is collapsed.
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