Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: chrome/browser/win/enumerate_modules_model.cc

Issue 2670763007: Use TaskScheduler instead of blocking pool in enumerate_modules_model.cc. (Closed)
Patch Set: CR and fix build error" Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/win/enumerate_modules_model.h" 5 #include "chrome/browser/win/enumerate_modules_model.h"
6 6
7 #include <softpub.h> 7 #include <softpub.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 #include <tlhelp32.h> 10 #include <tlhelp32.h>
(...skipping 10 matching lines...) Expand all
21 #include "base/debug/leak_annotations.h" 21 #include "base/debug/leak_annotations.h"
22 #include "base/environment.h" 22 #include "base/environment.h"
23 #include "base/file_version_info.h" 23 #include "base/file_version_info.h"
24 #include "base/i18n/case_conversion.h" 24 #include "base/i18n/case_conversion.h"
25 #include "base/macros.h" 25 #include "base/macros.h"
26 #include "base/metrics/histogram_macros.h" 26 #include "base/metrics/histogram_macros.h"
27 #include "base/scoped_generic.h" 27 #include "base/scoped_generic.h"
28 #include "base/strings/string_number_conversions.h" 28 #include "base/strings/string_number_conversions.h"
29 #include "base/strings/string_util.h" 29 #include "base/strings/string_util.h"
30 #include "base/strings/utf_string_conversions.h" 30 #include "base/strings/utf_string_conversions.h"
31 #include "base/threading/sequenced_worker_pool.h" 31 #include "base/task_scheduler/post_task.h"
32 #include "base/time/time.h" 32 #include "base/time/time.h"
33 #include "base/values.h" 33 #include "base/values.h"
34 #include "base/version.h" 34 #include "base/version.h"
35 #include "base/win/registry.h" 35 #include "base/win/registry.h"
36 #include "base/win/scoped_handle.h" 36 #include "base/win/scoped_handle.h"
37 #include "base/win/windows_version.h" 37 #include "base/win/windows_version.h"
38 #include "chrome/browser/net/service_providers_win.h" 38 #include "chrome/browser/net/service_providers_win.h"
39 #include "chrome/common/chrome_constants.h" 39 #include "chrome/common/chrome_constants.h"
40 #include "chrome/common/crash_keys.h" 40 #include "chrome/common/crash_keys.h"
41 #include "chrome/grit/generated_resources.h" 41 #include "chrome/grit/generated_resources.h"
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 if (first_space != base::string16::npos) 156 if (first_space != base::string16::npos)
157 module->version = module->version.substr(0, first_space); 157 module->version = module->version.substr(0, first_space);
158 158
159 // The signer may be returned with trailing nulls. 159 // The signer may be returned with trailing nulls.
160 size_t first_null = module->cert_info.subject.find(L'\0'); 160 size_t first_null = module->cert_info.subject.find(L'\0');
161 if (first_null != base::string16::npos) 161 if (first_null != base::string16::npos)
162 module->cert_info.subject.resize(first_null); 162 module->cert_info.subject.resize(first_null);
163 } 163 }
164 164
165 ModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer) 165 ModuleEnumerator::ModuleEnumerator(EnumerateModulesModel* observer)
166 : enumerated_modules_(nullptr), 166 : background_task_runner_(base::CreateTaskRunnerWithTraits(
167 base::TaskTraits()
168 .MayBlock()
169 .WithPriority(base::TaskPriority::BACKGROUND)
170 .WithShutdownBehavior(
171 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN))),
172 enumerated_modules_(nullptr),
167 observer_(observer), 173 observer_(observer),
168 per_module_delay_(kDefaultPerModuleDelay) { 174 per_module_delay_(kDefaultPerModuleDelay) {}
169 }
170 175
171 ModuleEnumerator::~ModuleEnumerator() { 176 ModuleEnumerator::~ModuleEnumerator() {
172 } 177 }
173 178
174 void ModuleEnumerator::ScanNow(ModulesVector* list) { 179 void ModuleEnumerator::ScanNow(ModulesVector* list) {
175 DCHECK_CURRENTLY_ON(BrowserThread::UI); 180 DCHECK_CURRENTLY_ON(BrowserThread::UI);
176 enumerated_modules_ = list; 181 enumerated_modules_ = list;
177 182
178 // This object can't be reaped until it has finished scanning, so its safe 183 // This object can't be reaped until it has finished scanning, so its safe
179 // to post a raw pointer to another thread. It will simply be leaked if the 184 // to post a raw pointer to another thread. It will simply be leaked if the
180 // scanning has not been finished before shutdown. 185 // scanning has not been finished before shutdown.
181 BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( 186 background_task_runner_->PostTask(
182 FROM_HERE, 187 FROM_HERE,
183 base::Bind(&ModuleEnumerator::ScanImplStart, 188 base::Bind(&ModuleEnumerator::ScanImplStart, base::Unretained(this)));
184 base::Unretained(this)),
185 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
186 } 189 }
187 190
188 void ModuleEnumerator::SetPerModuleDelayToZero() { 191 void ModuleEnumerator::SetPerModuleDelayToZero() {
189 // Set the delay to zero so the modules enumerate as quickly as possible. 192 // Set the delay to zero so the modules enumerate as quickly as possible.
190 per_module_delay_ = base::TimeDelta::FromSeconds(0); 193 per_module_delay_ = base::TimeDelta::FromSeconds(0);
191 } 194 }
192 195
193 void ModuleEnumerator::ScanImplStart() { 196 void ModuleEnumerator::ScanImplStart() {
194 base::TimeTicks start_time = base::TimeTicks::Now(); 197 base::TimeTicks start_time = base::TimeTicks::Now();
195 198
(...skipping 22 matching lines...) Expand all
218 checkpoint = checkpoint2; 221 checkpoint = checkpoint2;
219 EnumerateWinsockModules(); 222 EnumerateWinsockModules();
220 checkpoint2 = base::TimeTicks::Now(); 223 checkpoint2 = base::TimeTicks::Now();
221 UMA_HISTOGRAM_TIMES("Conflicts.EnumerateWinsockModules", 224 UMA_HISTOGRAM_TIMES("Conflicts.EnumerateWinsockModules",
222 checkpoint2 - checkpoint); 225 checkpoint2 - checkpoint);
223 226
224 enumeration_total_time_ = base::TimeTicks::Now() - start_time; 227 enumeration_total_time_ = base::TimeTicks::Now() - start_time;
225 228
226 // Post a delayed task to scan the first module. This forwards directly to 229 // Post a delayed task to scan the first module. This forwards directly to
227 // ScanImplFinish if there are no modules to scan. 230 // ScanImplFinish if there are no modules to scan.
228 BrowserThread::GetBlockingPool()->PostDelayedWorkerTask( 231 background_task_runner_->PostDelayedTask(
229 FROM_HERE, 232 FROM_HERE,
230 base::Bind(&ModuleEnumerator::ScanImplModule, 233 base::Bind(&ModuleEnumerator::ScanImplModule, base::Unretained(this), 0),
231 base::Unretained(this),
232 0),
233 per_module_delay_); 234 per_module_delay_);
234 } 235 }
235 236
236 void ModuleEnumerator::ScanImplDelay(size_t index) {
237 // Bounce this over to a CONTINUE_ON_SHUTDOWN task in the same pool. This is
238 // necessary to prevent shutdown hangs while inspecting a module.
239 BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
240 FROM_HERE,
241 base::Bind(&ModuleEnumerator::ScanImplModule,
242 base::Unretained(this),
243 index),
244 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
245 }
246
247 void ModuleEnumerator::ScanImplModule(size_t index) { 237 void ModuleEnumerator::ScanImplModule(size_t index) {
248 while (index < enumerated_modules_->size()) { 238 while (index < enumerated_modules_->size()) {
249 base::TimeTicks start_time = base::TimeTicks::Now(); 239 base::TimeTicks start_time = base::TimeTicks::Now();
250 Module& entry = enumerated_modules_->at(index); 240 Module& entry = enumerated_modules_->at(index);
251 PopulateModuleInformation(&entry); 241 PopulateModuleInformation(&entry);
252 NormalizeModule(&entry); 242 NormalizeModule(&entry);
253 CollapsePath(&entry); 243 CollapsePath(&entry);
254 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; 244 base::TimeDelta elapsed = base::TimeTicks::Now() - start_time;
255 enumeration_inspection_time_ += elapsed; 245 enumeration_inspection_time_ += elapsed;
256 enumeration_total_time_ += elapsed; 246 enumeration_total_time_ += elapsed;
257 247
258 // With a non-zero delay, bounce back over to ScanImplDelay, which will 248 // If |per_module_delay_| is non-zero, post a task to scan the next module
259 // bounce back to this function and inspect the next module. 249 // when the delay expires.
260 if (!per_module_delay_.is_zero()) { 250 if (!per_module_delay_.is_zero()) {
261 BrowserThread::GetBlockingPool()->PostDelayedWorkerTask( 251 background_task_runner_->PostDelayedTask(
262 FROM_HERE, 252 FROM_HERE, base::Bind(&ModuleEnumerator::ScanImplModule,
263 base::Bind(&ModuleEnumerator::ScanImplDelay, 253 base::Unretained(this), index + 1),
264 base::Unretained(this),
265 index + 1),
266 per_module_delay_); 254 per_module_delay_);
267 return; 255 return;
268 } 256 }
269 257
270 // If the delay has been set to zero then simply finish the rest of the 258 // If the delay has been set to zero then simply finish the rest of the
271 // enumeration in this already started task. 259 // enumeration in this already started task.
272 ++index; 260 ++index;
273 } 261 }
274 262
275 // Getting here means that all of the modules have been inspected. 263 // Getting here means that all of the modules have been inspected.
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 base::Unretained(this), 594 base::Unretained(this),
607 true)); 595 true));
608 done = true; 596 done = true;
609 } 597 }
610 } 598 }
611 599
612 void EnumerateModulesModel::ScanNow(bool background_mode) { 600 void EnumerateModulesModel::ScanNow(bool background_mode) {
613 DCHECK_CURRENTLY_ON(BrowserThread::UI); 601 DCHECK_CURRENTLY_ON(BrowserThread::UI);
614 602
615 // |module_enumerator_| is used as a lock to know whether or not there are 603 // |module_enumerator_| is used as a lock to know whether or not there are
616 // active/pending blocking pool tasks. If a module enumerator exists then a 604 // active/pending background tasks. If a module enumerator exists then a scan
617 // scan is already underway. Otherwise, either no scan has been completed or 605 // is already underway. Otherwise, either no scan has been completed or a scan
618 // a scan has terminated. 606 // has terminated.
619 if (module_enumerator_) { 607 if (module_enumerator_) {
620 // If a scan is in progress and this request is for immediate results, then 608 // If a scan is in progress and this request is for immediate results, then
621 // inform the background scan. This is done without any locks because the 609 // inform the background scan. This is done without any locks because the
622 // other thread only reads from the value that is being modified, and on 610 // other thread only reads from the value that is being modified, and on
623 // Windows its an atomic write. 611 // Windows its an atomic write.
624 if (!background_mode) 612 if (!background_mode)
625 module_enumerator_->SetPerModuleDelayToZero(); 613 module_enumerator_->SetPerModuleDelayToZero();
626 return; 614 return;
627 } 615 }
628 616
629 // Only allow a single scan per process lifetime. Immediately notify any 617 // Only allow a single scan per process lifetime. Immediately notify any
630 // observers that the scan is complete. At this point |enumerated_modules_| is 618 // observers that the scan is complete. At this point |enumerated_modules_| is
631 // safe to access as no potentially racing blocking pool task can exist. 619 // safe to access as no potentially racing background task can exist.
632 if (!enumerated_modules_.empty()) { 620 if (!enumerated_modules_.empty()) {
633 for (Observer& observer : observers_) 621 for (Observer& observer : observers_)
634 observer.OnScanCompleted(); 622 observer.OnScanCompleted();
635 return; 623 return;
636 } 624 }
637 625
638 // ScanNow does not block, rather it simply schedules a task. 626 // ScanNow does not block, rather it simply schedules a task.
639 module_enumerator_.reset(new ModuleEnumerator(this)); 627 module_enumerator_.reset(new ModuleEnumerator(this));
640 if (!background_mode) 628 if (!background_mode)
641 module_enumerator_->SetPerModuleDelayToZero(); 629 module_enumerator_->SetPerModuleDelayToZero();
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 759
772 UMA_HISTOGRAM_COUNTS_100("Conflicts.SuspectedBadModules", 760 UMA_HISTOGRAM_COUNTS_100("Conflicts.SuspectedBadModules",
773 suspected_bad_modules_detected_); 761 suspected_bad_modules_detected_);
774 UMA_HISTOGRAM_COUNTS_100("Conflicts.ConfirmedBadModules", 762 UMA_HISTOGRAM_COUNTS_100("Conflicts.ConfirmedBadModules",
775 confirmed_bad_modules_detected_); 763 confirmed_bad_modules_detected_);
776 764
777 // Forward the callback to any registered observers. 765 // Forward the callback to any registered observers.
778 for (Observer& observer : observers_) 766 for (Observer& observer : observers_)
779 observer.OnScanCompleted(); 767 observer.OnScanCompleted();
780 } 768 }
OLDNEW
« no previous file with comments | « chrome/browser/win/enumerate_modules_model.h ('k') | chrome/browser/win/enumerate_modules_model_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698