Chromium Code Reviews| Index: net/dns/host_resolver_impl.cc |
| diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc |
| index 5559c8d460fbbed748f66146ac784f2d8e1cf9d7..d738d5536bb122661ae2b2c0eb69d97711d0653e 100644 |
| --- a/net/dns/host_resolver_impl.cc |
| +++ b/net/dns/host_resolver_impl.cc |
| @@ -24,8 +24,10 @@ |
| #include "base/callback.h" |
| #include "base/compiler_specific.h" |
| #include "base/debug/debugger.h" |
| +#include "base/debug/leak_annotations.h" |
| #include "base/debug/stack_trace.h" |
| #include "base/macros.h" |
| +#include "base/memory/ptr_util.h" |
| #include "base/metrics/field_trial.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/metrics/sparse_histogram.h" |
| @@ -621,11 +623,13 @@ class HostResolverImpl::ProcTask |
| ProcTask(const Key& key, |
| const ProcTaskParams& params, |
| const Callback& callback, |
| + scoped_refptr<base::TaskRunner> worker_task_runner, |
| const BoundNetLog& job_net_log) |
| : key_(key), |
| params_(params), |
| callback_(callback), |
| - task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| + worker_task_runner_(std::move(worker_task_runner)), |
| + network_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| attempt_number_(0), |
| completed_attempt_number_(0), |
| completed_attempt_error_(ERR_UNEXPECTED), |
| @@ -639,7 +643,7 @@ class HostResolverImpl::ProcTask |
| } |
| void Start() { |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| net_log_.BeginEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_PROC_TASK); |
| StartLookupAttempt(); |
| } |
| @@ -648,7 +652,7 @@ class HostResolverImpl::ProcTask |
| // attempts running on worker threads will continue running. Only once all the |
| // attempts complete will the final reference to this ProcTask be released. |
| void Cancel() { |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| if (was_canceled() || was_completed()) |
| return; |
| @@ -658,17 +662,17 @@ class HostResolverImpl::ProcTask |
| } |
| void set_had_non_speculative_request() { |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| had_non_speculative_request_ = true; |
| } |
| bool was_canceled() const { |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| return callback_.is_null(); |
| } |
| bool was_completed() const { |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| return completed_attempt_number_ > 0; |
| } |
| @@ -677,27 +681,24 @@ class HostResolverImpl::ProcTask |
| ~ProcTask() {} |
| void StartLookupAttempt() { |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| base::TimeTicks start_time = base::TimeTicks::Now(); |
| ++attempt_number_; |
| // Dispatch the lookup attempt to a worker thread. |
| - if (!base::WorkerPool::PostTask( |
| - FROM_HERE, |
| - base::Bind(&ProcTask::DoLookup, this, start_time, attempt_number_), |
| - true)) { |
| + // TODO(mmenke): Chrome code generally doesn't handle failed PostTasks. |
|
eroman
2016/05/17 23:01:34
Arguably that other code is wrong :)
Also best not
mmenke
2016/05/19 19:09:45
Just removed the TODO. In Chrome, the preference
|
| + // Should this code really be any different? |
| + if (!worker_task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&ProcTask::DoLookup, this, start_time, |
| + attempt_number_))) { |
| NOTREACHED(); |
| - // Since we could be running within Resolve() right now, we can't just |
| - // call OnLookupComplete(). Instead we must wait until Resolve() has |
| - // returned (IO_PENDING). |
| - task_runner_->PostTask(FROM_HERE, |
| - base::Bind(&ProcTask::OnLookupComplete, |
| - this, |
| - AddressList(), |
| - start_time, |
| - attempt_number_, |
| - ERR_UNEXPECTED, |
| - 0)); |
| + // Since this method may have been called from Resolve(), can't just call |
| + // OnLookupComplete(). Instead, must wait until Resolve() has returned |
| + // (IO_PENDING). |
| + network_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&ProcTask::OnLookupComplete, this, AddressList(), |
| + start_time, attempt_number_, ERR_UNEXPECTED, 0)); |
| return; |
| } |
| @@ -708,9 +709,8 @@ class HostResolverImpl::ProcTask |
| // will start a new attempt on a different worker thread if none of our |
| // outstanding attempts have completed yet. |
| if (attempt_number_ <= params_.max_retry_attempts) { |
| - task_runner_->PostDelayedTask( |
| - FROM_HERE, |
| - base::Bind(&ProcTask::RetryIfNotComplete, this), |
| + network_task_runner_->PostDelayedTask( |
| + FROM_HERE, base::Bind(&ProcTask::RetryIfNotComplete, this), |
| params_.unresponsive_delay); |
| } |
| } |
| @@ -741,20 +741,15 @@ class HostResolverImpl::ProcTask |
| } |
| } |
| - task_runner_->PostTask(FROM_HERE, |
| - base::Bind(&ProcTask::OnLookupComplete, |
| - this, |
| - results, |
| - start_time, |
| - attempt_number, |
| - error, |
| - os_error)); |
| + network_task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&ProcTask::OnLookupComplete, this, results, |
| + start_time, attempt_number, error, os_error)); |
| } |
| // Makes next attempt if DoLookup() has not finished (runs on task runner |
|
eroman
2016/05/17 23:01:34
update "task runner" in comment (which is now ambi
mmenke
2016/05/19 19:09:45
Removed the comment, agree the DCHECK is sufficien
|
| // thread). |
| void RetryIfNotComplete() { |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| if (was_completed() || was_canceled()) |
| return; |
| @@ -770,7 +765,7 @@ class HostResolverImpl::ProcTask |
| int error, |
| const int os_error) { |
| TRACE_EVENT0("net", "ProcTask::OnLookupComplete"); |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| // If results are empty, we should return an error. |
| bool empty_list_on_ok = (error == OK && results.empty()); |
| UMA_HISTOGRAM_BOOLEAN("DNS.EmptyAddressListAndNoError", empty_list_on_ok); |
| @@ -836,7 +831,7 @@ class HostResolverImpl::ProcTask |
| void RecordPerformanceHistograms(const base::TimeTicks& start_time, |
| const int error, |
| const int os_error) const { |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| enum Category { // Used in UMA_HISTOGRAM_ENUMERATION. |
| RESOLVE_SUCCESS, |
| RESOLVE_FAIL, |
| @@ -903,7 +898,7 @@ class HostResolverImpl::ProcTask |
| const uint32_t attempt_number, |
| const int error, |
| const int os_error) const { |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| bool first_attempt_to_complete = |
| completed_attempt_number_ == attempt_number; |
| bool is_first_attempt = (attempt_number == 1); |
| @@ -962,8 +957,11 @@ class HostResolverImpl::ProcTask |
| // The listener to the results of this ProcTask. |
| Callback callback_; |
| - // Used to post ourselves onto the task runner thread. |
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| + // Task runner for the call to the platform address resolver. |
|
eroman
2016/05/17 23:01:34
Not necessarily using the "platform" address resol
mmenke
2016/05/19 19:09:45
Done.
|
| + scoped_refptr<base::TaskRunner> worker_task_runner_; |
| + |
| + // Used to post events onto the network thread. |
|
eroman
2016/05/17 23:01:34
I wonder if "origin" vs "worker" would be more cle
mmenke
2016/05/19 19:09:45
I prefer network thread. "network thread" sounds
|
| + scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; |
| // Keeps track of the number of attempts we have made so far to resolve the |
| // host. Whenever we start an attempt to resolve the host, we increase this |
| @@ -999,16 +997,19 @@ class HostResolverImpl::ProcTask |
| // it takes 40-100ms and should not block initialization. |
| class HostResolverImpl::LoopbackProbeJob { |
| public: |
| - explicit LoopbackProbeJob(const base::WeakPtr<HostResolverImpl>& resolver) |
| - : resolver_(resolver), |
| - result_(false) { |
| + LoopbackProbeJob(const base::WeakPtr<HostResolverImpl>& resolver, |
| + base::TaskRunner* worker_task_runner) |
| + : resolver_(resolver), result_(false) { |
| DCHECK(resolver.get()); |
| - const bool kIsSlow = true; |
| - base::WorkerPool::PostTaskAndReply( |
| + // Do not report worker pool leaks in tests. The WorkerPool doesn't have a |
| + // flushing API, so can't do anything about them, other than using another |
| + // task runner. |
| + // http://crbug.com/248513 |
| + ANNOTATE_SCOPED_MEMORY_LEAK; |
| + worker_task_runner->PostTaskAndReply( |
| FROM_HERE, |
| base::Bind(&LoopbackProbeJob::DoProbe, base::Unretained(this)), |
| - base::Bind(&LoopbackProbeJob::OnProbeComplete, base::Owned(this)), |
| - kIsSlow); |
| + base::Bind(&LoopbackProbeJob::OnProbeComplete, base::Owned(this))); |
| } |
| virtual ~LoopbackProbeJob() {} |
| @@ -1270,10 +1271,12 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job, |
| Job(const base::WeakPtr<HostResolverImpl>& resolver, |
| const Key& key, |
| RequestPriority priority, |
| + scoped_refptr<base::TaskRunner> worker_task_runner, |
| const BoundNetLog& source_net_log) |
| : resolver_(resolver), |
| key_(key), |
| priority_tracker_(priority), |
| + worker_task_runner_(std::move(worker_task_runner)), |
| had_non_speculative_request_(false), |
| had_dns_config_(false), |
| num_occupied_job_slots_(0), |
| @@ -1549,12 +1552,11 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job, |
| // tighter limits. |
| void StartProcTask() { |
| DCHECK(!is_dns_running()); |
| - proc_task_ = new ProcTask( |
| - key_, |
| - resolver_->proc_params_, |
| - base::Bind(&Job::OnProcTaskComplete, base::Unretained(this), |
| - base::TimeTicks::Now()), |
| - net_log_); |
| + proc_task_ = |
| + new ProcTask(key_, resolver_->proc_params_, |
| + base::Bind(&Job::OnProcTaskComplete, |
| + base::Unretained(this), base::TimeTicks::Now()), |
| + worker_task_runner_, net_log_); |
| if (had_non_speculative_request_) |
| proc_task_->set_had_non_speculative_request(); |
| @@ -1816,6 +1818,9 @@ class HostResolverImpl::Job : public PrioritizedDispatcher::Job, |
| // Tracks the highest priority across |requests_|. |
| PriorityTracker priority_tracker_; |
| + // Task runner where the HostResolverProc is invoked. |
| + scoped_refptr<base::TaskRunner> worker_task_runner_; |
| + |
| bool had_non_speculative_request_; |
| // Distinguishes measurements taken while DnsClient was fully configured. |
| @@ -1867,53 +1872,10 @@ HostResolverImpl::ProcTaskParams::ProcTaskParams(const ProcTaskParams& other) = |
| HostResolverImpl::ProcTaskParams::~ProcTaskParams() {} |
| HostResolverImpl::HostResolverImpl(const Options& options, NetLog* net_log) |
| - : max_queued_jobs_(0), |
| - proc_params_(NULL, options.max_retry_attempts), |
| - net_log_(net_log), |
| - received_dns_config_(false), |
| - num_dns_failures_(0), |
| - use_local_ipv6_(false), |
| - last_ipv6_probe_result_(true), |
| - resolved_known_ipv6_hostname_(false), |
| - additional_resolver_flags_(0), |
| - fallback_to_proctask_(true), |
| - weak_ptr_factory_(this), |
| - probe_weak_ptr_factory_(this) { |
| - if (options.enable_caching) |
| - cache_ = HostCache::CreateDefaultCache(); |
| - |
| - PrioritizedDispatcher::Limits job_limits = options.GetDispatcherLimits(); |
| - dispatcher_.reset(new PrioritizedDispatcher(job_limits)); |
| - max_queued_jobs_ = job_limits.total_jobs * 100u; |
| - |
| - DCHECK_GE(dispatcher_->num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); |
| - |
| -#if defined(OS_WIN) |
| - EnsureWinsockInit(); |
| -#endif |
| -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
| - new LoopbackProbeJob(weak_ptr_factory_.GetWeakPtr()); |
| -#endif |
| - NetworkChangeNotifier::AddIPAddressObserver(this); |
| - NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| - NetworkChangeNotifier::AddDNSObserver(this); |
| -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \ |
| - !defined(OS_ANDROID) |
| - EnsureDnsReloaderInit(); |
| -#endif |
| - |
| - OnConnectionTypeChanged(NetworkChangeNotifier::GetConnectionType()); |
| - |
| - { |
| - DnsConfig dns_config; |
| - NetworkChangeNotifier::GetDnsConfig(&dns_config); |
| - received_dns_config_ = dns_config.IsValid(); |
| - // Conservatively assume local IPv6 is needed when DnsConfig is not valid. |
| - use_local_ipv6_ = !dns_config.IsValid() || dns_config.use_local_ipv6; |
| - } |
| - |
| - fallback_to_proctask_ = !ConfigureAsyncDnsNoFallbackFieldTrial(); |
| -} |
| + : HostResolverImpl( |
| + options, |
| + net_log, |
| + base::WorkerPool::GetTaskRunner(true /* task_is_slow */)) {} |
| HostResolverImpl::~HostResolverImpl() { |
| // Prevent the dispatcher from starting new jobs. |
| @@ -1972,8 +1934,8 @@ int HostResolverImpl::Resolve(const RequestInfo& info, |
| JobMap::iterator jobit = jobs_.find(key); |
| Job* job; |
| if (jobit == jobs_.end()) { |
| - job = |
| - new Job(weak_ptr_factory_.GetWeakPtr(), key, priority, source_net_log); |
| + job = new Job(weak_ptr_factory_.GetWeakPtr(), key, priority, |
| + worker_task_runner_, source_net_log); |
| job->Schedule(false); |
| // Check for queue overflow. |
| @@ -2003,6 +1965,67 @@ int HostResolverImpl::Resolve(const RequestInfo& info, |
| return ERR_IO_PENDING; |
| } |
| +HostResolverImpl::HostResolverImpl( |
| + const Options& options, |
| + NetLog* net_log, |
| + scoped_refptr<base::TaskRunner> worker_task_runner) |
| + : max_queued_jobs_(0), |
| + proc_params_(NULL, options.max_retry_attempts), |
| + net_log_(net_log), |
| + received_dns_config_(false), |
| + num_dns_failures_(0), |
| + use_local_ipv6_(false), |
| + last_ipv6_probe_result_(true), |
| + resolved_known_ipv6_hostname_(false), |
| + additional_resolver_flags_(0), |
| + fallback_to_proctask_(true), |
| + worker_task_runner_(std::move(worker_task_runner)), |
| + weak_ptr_factory_(this), |
| + probe_weak_ptr_factory_(this) { |
| + if (options.enable_caching) |
| + cache_ = HostCache::CreateDefaultCache(); |
| + |
| + PrioritizedDispatcher::Limits job_limits = options.GetDispatcherLimits(); |
| + dispatcher_.reset(new PrioritizedDispatcher(job_limits)); |
| + max_queued_jobs_ = job_limits.total_jobs * 100u; |
| + |
| + DCHECK_GE(dispatcher_->num_priorities(), static_cast<size_t>(NUM_PRIORITIES)); |
| + |
| +#if defined(OS_WIN) |
| + EnsureWinsockInit(); |
| +#endif |
| +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
| + RunLoopbackProbeJob(); |
| +#endif |
| + NetworkChangeNotifier::AddIPAddressObserver(this); |
| + NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| + NetworkChangeNotifier::AddDNSObserver(this); |
| +#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \ |
| + !defined(OS_ANDROID) |
| + EnsureDnsReloaderInit(); |
| +#endif |
| + |
| + OnConnectionTypeChanged(NetworkChangeNotifier::GetConnectionType()); |
| + |
| + { |
| + DnsConfig dns_config; |
| + NetworkChangeNotifier::GetDnsConfig(&dns_config); |
| + received_dns_config_ = dns_config.IsValid(); |
| + // Conservatively assume local IPv6 is needed when DnsConfig is not valid. |
| + use_local_ipv6_ = !dns_config.IsValid() || dns_config.use_local_ipv6; |
| + } |
| + |
| + fallback_to_proctask_ = !ConfigureAsyncDnsNoFallbackFieldTrial(); |
| +} |
| + |
| +void HostResolverImpl::SetHaveOnlyLoopbackAddresses(bool result) { |
| + if (result) { |
| + additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; |
| + } else { |
| + additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY; |
| + } |
| +} |
| + |
| int HostResolverImpl::ResolveHelper(const Key& key, |
| const RequestInfo& info, |
| const IPAddress* ip_address, |
| @@ -2241,14 +2264,6 @@ void HostResolverImpl::RemoveJob(Job* job) { |
| jobs_.erase(it); |
| } |
| -void HostResolverImpl::SetHaveOnlyLoopbackAddresses(bool result) { |
| - if (result) { |
| - additional_resolver_flags_ |= HOST_RESOLVER_LOOPBACK_ONLY; |
| - } else { |
| - additional_resolver_flags_ &= ~HOST_RESOLVER_LOOPBACK_ONLY; |
| - } |
| -} |
| - |
| HostResolverImpl::Key HostResolverImpl::GetEffectiveKeyForRequest( |
| const RequestInfo& info, |
| const IPAddress* ip_address, |
| @@ -2291,6 +2306,11 @@ bool HostResolverImpl::IsIPv6Reachable(const BoundNetLog& net_log) { |
| return last_ipv6_probe_result_; |
| } |
| +void HostResolverImpl::RunLoopbackProbeJob() { |
| + new LoopbackProbeJob(weak_ptr_factory_.GetWeakPtr(), |
| + worker_task_runner_.get()); |
| +} |
| + |
| void HostResolverImpl::AbortAllInProgressJobs() { |
| // In Abort, a Request callback could spawn new Jobs with matching keys, so |
| // first collect and remove all running jobs from |jobs_|. |
| @@ -2366,7 +2386,7 @@ void HostResolverImpl::OnIPAddressChanged() { |
| if (cache_.get()) |
| cache_->clear(); |
| #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
| - new LoopbackProbeJob(probe_weak_ptr_factory_.GetWeakPtr()); |
| + RunLoopbackProbeJob(); |
| #endif |
| AbortAllInProgressJobs(); |
| // |this| may be deleted inside AbortAllInProgressJobs(). |