OLD | NEW |
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/browser_process_impl.h" | 5 #include "chrome/browser/browser_process_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <iterator> |
10 #include <map> | 11 #include <map> |
11 #include <utility> | 12 #include <utility> |
12 #include <vector> | 13 #include <vector> |
13 | 14 |
14 #include "base/atomic_ref_count.h" | 15 #include "base/atomic_ref_count.h" |
15 #include "base/bind.h" | 16 #include "base/bind.h" |
16 #include "base/bind_helpers.h" | 17 #include "base/bind_helpers.h" |
17 #include "base/command_line.h" | 18 #include "base/command_line.h" |
18 #include "base/debug/crash_logging.h" | 19 #include "base/debug/crash_logging.h" |
19 #include "base/debug/leak_annotations.h" | 20 #include "base/debug/leak_annotations.h" |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 // | 392 // |
392 // This is important also because in various places, the | 393 // This is important also because in various places, the |
393 // IOThread object being NULL is considered synonymous with the | 394 // IOThread object being NULL is considered synonymous with the |
394 // IO thread having stopped. | 395 // IO thread having stopped. |
395 io_thread_.reset(); | 396 io_thread_.reset(); |
396 } | 397 } |
397 #endif // !defined(OS_ANDROID) | 398 #endif // !defined(OS_ANDROID) |
398 | 399 |
399 namespace { | 400 namespace { |
400 | 401 |
| 402 using TaskRunnerVector = std::vector<scoped_refptr<base::SequencedTaskRunner>>; |
| 403 |
401 // Used at the end of session to block the UI thread for completion of sentinel | 404 // Used at the end of session to block the UI thread for completion of sentinel |
402 // tasks on the set of threads used to persist profile data and local state. | 405 // tasks on the set of threads used to persist profile data and local state. |
403 // This is done to ensure that the data has been persisted to disk before | 406 // This is done to ensure that the data has been persisted to disk before |
404 // continuing. | 407 // continuing. |
405 class RundownTaskCounter : | 408 class RundownTaskCounter : |
406 public base::RefCountedThreadSafe<RundownTaskCounter> { | 409 public base::RefCountedThreadSafe<RundownTaskCounter> { |
407 public: | 410 public: |
408 RundownTaskCounter(); | 411 RundownTaskCounter(); |
409 | 412 |
410 // Posts a rundown task to |task_runner|, can be invoked an arbitrary number | 413 // Posts a rundown task to |task_runner|, can be invoked an arbitrary number |
411 // of times before calling TimedWait. | 414 // of times before calling TimedWait. |
412 void Post(base::SequencedTaskRunner* task_runner); | 415 void Post(base::SequencedTaskRunner* task_runner); |
413 | 416 |
| 417 // Posts a rundown task to each runner in |runners|, where the rundown task |
| 418 // for runner[n+1] is posted during rundown task execution for runner[n]. |
| 419 void PostSerially(TaskRunnerVector runners); |
| 420 |
414 // Waits until the count is zero or |end_time| is reached. | 421 // Waits until the count is zero or |end_time| is reached. |
415 // This can only be called once per instance. Returns true if a count of zero | 422 // This can only be called once per instance. Returns true if a count of zero |
416 // is reached or false if the |end_time| is reached. It is valid to pass an | 423 // is reached or false if the |end_time| is reached. It is valid to pass an |
417 // |end_time| in the past. | 424 // |end_time| in the past. |
418 bool TimedWaitUntil(const base::TimeTicks& end_time); | 425 bool TimedWaitUntil(const base::TimeTicks& end_time); |
419 | 426 |
420 private: | 427 private: |
421 friend class base::RefCountedThreadSafe<RundownTaskCounter>; | 428 friend class base::RefCountedThreadSafe<RundownTaskCounter>; |
422 ~RundownTaskCounter() {} | 429 ~RundownTaskCounter() {} |
423 | 430 |
424 // Decrements the counter and releases the waitable event on transition to | 431 // Decrements the counter and releases the waitable event on transition to |
425 // zero. | 432 // zero. |
426 void Decrement(); | 433 void Decrement(); |
427 | 434 |
| 435 void RundownSerially(TaskRunnerVector::const_iterator it, |
| 436 TaskRunnerVector runner); |
| 437 |
428 // The count starts at one to defer the possibility of one->zero transitions | 438 // The count starts at one to defer the possibility of one->zero transitions |
429 // until TimedWait is called. | 439 // until TimedWait is called. |
430 base::AtomicRefCount count_; | 440 base::AtomicRefCount count_; |
431 base::WaitableEvent waitable_event_; | 441 base::WaitableEvent waitable_event_; |
432 | 442 |
433 DISALLOW_COPY_AND_ASSIGN(RundownTaskCounter); | 443 DISALLOW_COPY_AND_ASSIGN(RundownTaskCounter); |
434 }; | 444 }; |
435 | 445 |
436 RundownTaskCounter::RundownTaskCounter() | 446 RundownTaskCounter::RundownTaskCounter() |
437 : count_(1), | 447 : count_(1), |
438 waitable_event_(base::WaitableEvent::ResetPolicy::MANUAL, | 448 waitable_event_(base::WaitableEvent::ResetPolicy::MANUAL, |
439 base::WaitableEvent::InitialState::NOT_SIGNALED) {} | 449 base::WaitableEvent::InitialState::NOT_SIGNALED) {} |
440 | 450 |
441 void RundownTaskCounter::Post(base::SequencedTaskRunner* task_runner) { | 451 void RundownTaskCounter::Post(base::SequencedTaskRunner* task_runner) { |
442 // As the count starts off at one, it should never get to zero unless | 452 // As the count starts off at one, it should never get to zero unless |
443 // TimedWait has been called. | 453 // TimedWait has been called. |
444 DCHECK(!base::AtomicRefCountIsZero(&count_)); | 454 DCHECK(!base::AtomicRefCountIsZero(&count_)); |
445 | 455 |
446 base::AtomicRefCountInc(&count_); | 456 base::AtomicRefCountInc(&count_); |
447 | 457 |
448 // The task must be non-nestable to guarantee that it runs after all tasks | 458 // The task must be non-nestable to guarantee that it runs after all tasks |
449 // currently scheduled on |task_runner| have completed. | 459 // currently scheduled on |task_runner| have completed. |
450 task_runner->PostNonNestableTask(FROM_HERE, | 460 task_runner->PostNonNestableTask(FROM_HERE, |
451 base::Bind(&RundownTaskCounter::Decrement, this)); | 461 base::Bind(&RundownTaskCounter::Decrement, this)); |
452 } | 462 } |
453 | 463 |
| 464 void RundownTaskCounter::PostSerially(TaskRunnerVector runners) { |
| 465 if (runners.empty()) |
| 466 return; |
| 467 base::AtomicRefCountInc(&count_); |
| 468 TaskRunnerVector::const_iterator it = runners.begin(); |
| 469 (*it)->PostNonNestableTask( |
| 470 FROM_HERE, base::Bind(&RundownTaskCounter::RundownSerially, this, it + 1, |
| 471 base::Passed(&runners))); |
| 472 } |
| 473 |
454 void RundownTaskCounter::Decrement() { | 474 void RundownTaskCounter::Decrement() { |
455 if (!base::AtomicRefCountDec(&count_)) | 475 if (!base::AtomicRefCountDec(&count_)) |
456 waitable_event_.Signal(); | 476 waitable_event_.Signal(); |
457 } | 477 } |
458 | 478 |
459 bool RundownTaskCounter::TimedWaitUntil(const base::TimeTicks& end_time) { | 479 bool RundownTaskCounter::TimedWaitUntil(const base::TimeTicks& end_time) { |
460 // Decrement the excess count from the constructor. | 480 // Decrement the excess count from the constructor. |
461 Decrement(); | 481 Decrement(); |
462 | 482 |
463 return waitable_event_.TimedWaitUntil(end_time); | 483 return waitable_event_.TimedWaitUntil(end_time); |
464 } | 484 } |
465 | 485 |
| 486 void RundownTaskCounter::RundownSerially(TaskRunnerVector::const_iterator it, |
| 487 TaskRunnerVector runners) { |
| 488 if (it == runners.end()) { |
| 489 Decrement(); |
| 490 return; |
| 491 } |
| 492 (*it)->PostNonNestableTask( |
| 493 FROM_HERE, base::Bind(&RundownTaskCounter::RundownSerially, this, it + 1, |
| 494 base::Passed(&runners))); |
| 495 } |
| 496 |
466 } // namespace | 497 } // namespace |
467 | 498 |
468 void BrowserProcessImpl::EndSession() { | 499 void BrowserProcessImpl::EndSession() { |
469 // Mark all the profiles as clean. | 500 // Mark all the profiles as clean. |
470 ProfileManager* pm = profile_manager(); | 501 ProfileManager* pm = profile_manager(); |
471 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); | 502 std::vector<Profile*> profiles(pm->GetLoadedProfiles()); |
472 scoped_refptr<RundownTaskCounter> rundown_counter(new RundownTaskCounter()); | 503 scoped_refptr<RundownTaskCounter> rundown_counter(new RundownTaskCounter()); |
473 const bool pref_service_enabled = | 504 const bool pref_service_enabled = |
474 base::FeatureList::IsEnabled(features::kPrefService); | 505 base::FeatureList::IsEnabled(features::kPrefService); |
475 std::vector<scoped_refptr<base::SequencedTaskRunner>> profile_writer_runners; | 506 std::vector<scoped_refptr<base::SequencedTaskRunner>> profile_writer_runners; |
476 for (size_t i = 0; i < profiles.size(); ++i) { | 507 for (Profile* profile : profiles) { |
477 Profile* profile = profiles[i]; | |
478 profile->SetExitType(Profile::EXIT_SESSION_ENDED); | 508 profile->SetExitType(Profile::EXIT_SESSION_ENDED); |
479 if (profile->GetPrefs()) { | 509 if (profile->GetPrefs()) { |
480 profile->GetPrefs()->CommitPendingWrite(); | 510 profile->GetPrefs()->CommitPendingWrite(); |
481 if (pref_service_enabled) { | 511 if (pref_service_enabled) { |
482 rundown_counter->Post(content::BrowserThread::GetTaskRunnerForThread( | 512 rundown_counter->Post(content::BrowserThread::GetTaskRunnerForThread( |
483 content::BrowserThread::IO) | 513 content::BrowserThread::IO) |
484 .get()); | 514 .get()); |
485 profile_writer_runners.push_back(profile->GetIOTaskRunner()); | 515 profile_writer_runners.push_back(profile->GetIOTaskRunner()); |
486 } else { | 516 } else { |
487 rundown_counter->Post(profile->GetIOTaskRunner().get()); | 517 rundown_counter->Post(profile->GetIOTaskRunner().get()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 // On Windows, we previously posted a message to FILE and then ran a nested | 550 // On Windows, we previously posted a message to FILE and then ran a nested |
521 // message loop, waiting for that message to be processed until quitting. | 551 // message loop, waiting for that message to be processed until quitting. |
522 // However, doing so means that other messages will also be processed. In | 552 // However, doing so means that other messages will also be processed. In |
523 // particular, if the GPU process host notices that the GPU has been killed | 553 // particular, if the GPU process host notices that the GPU has been killed |
524 // during shutdown, it races exiting the nested loop with the process host | 554 // during shutdown, it races exiting the nested loop with the process host |
525 // blocking the message loop attempting to re-establish a connection to the | 555 // blocking the message loop attempting to re-establish a connection to the |
526 // GPU process synchronously. Because the system may not be allowing | 556 // GPU process synchronously. Because the system may not be allowing |
527 // processes to launch, this can result in a hang. See | 557 // processes to launch, this can result in a hang. See |
528 // http://crbug.com/318527. | 558 // http://crbug.com/318527. |
529 const base::TimeTicks end_time = base::TimeTicks::Now() + kEndSessionTimeout; | 559 const base::TimeTicks end_time = base::TimeTicks::Now() + kEndSessionTimeout; |
530 const bool timed_out = !rundown_counter->TimedWaitUntil(end_time); | 560 if (!rundown_counter->TimedWaitUntil(end_time)) |
531 if (timed_out || !pref_service_enabled) | |
532 return; | 561 return; |
533 | 562 |
534 scoped_refptr<RundownTaskCounter> profile_write_rundown_counter( | 563 if (pref_service_enabled) { |
| 564 scoped_refptr<RundownTaskCounter> profile_write_rundown_counter( |
| 565 new RundownTaskCounter()); |
| 566 for (auto& profile_writer_runner : profile_writer_runners) |
| 567 profile_write_rundown_counter->Post(profile_writer_runner.get()); |
| 568 if (!profile_write_rundown_counter->TimedWaitUntil(end_time)) |
| 569 return; |
| 570 } |
| 571 |
| 572 // Time permitting, give other storage systems a chance to flush caches. |
| 573 auto flush_function = [](scoped_refptr<RundownTaskCounter> rundown_counter, |
| 574 content::StoragePartition* partition) { |
| 575 rundown_counter->PostSerially(partition->Flush()); |
| 576 }; |
| 577 scoped_refptr<RundownTaskCounter> flush_storage_rundown_counter( |
535 new RundownTaskCounter()); | 578 new RundownTaskCounter()); |
536 for (auto& profile_writer_runner : profile_writer_runners) | 579 for (Profile* profile : profiles) { |
537 profile_write_rundown_counter->Post(profile_writer_runner.get()); | 580 content::BrowserContext::ForEachStoragePartition( |
538 profile_write_rundown_counter->TimedWaitUntil(end_time); | 581 profile, |
| 582 base::BindRepeating(flush_function, flush_storage_rundown_counter)); |
| 583 } |
| 584 flush_storage_rundown_counter->TimedWaitUntil(end_time); |
539 #else | 585 #else |
540 NOTIMPLEMENTED(); | 586 NOTIMPLEMENTED(); |
541 #endif | 587 #endif |
542 } | 588 } |
543 | 589 |
544 metrics_services_manager::MetricsServicesManager* | 590 metrics_services_manager::MetricsServicesManager* |
545 BrowserProcessImpl::GetMetricsServicesManager() { | 591 BrowserProcessImpl::GetMetricsServicesManager() { |
546 DCHECK(CalledOnValidThread()); | 592 DCHECK(CalledOnValidThread()); |
547 if (!metrics_services_manager_) { | 593 if (!metrics_services_manager_) { |
548 metrics_services_manager_.reset( | 594 metrics_services_manager_.reset( |
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1435 } | 1481 } |
1436 | 1482 |
1437 void BrowserProcessImpl::OnAutoupdateTimer() { | 1483 void BrowserProcessImpl::OnAutoupdateTimer() { |
1438 if (CanAutorestartForUpdate()) { | 1484 if (CanAutorestartForUpdate()) { |
1439 DLOG(WARNING) << "Detected update. Restarting browser."; | 1485 DLOG(WARNING) << "Detected update. Restarting browser."; |
1440 RestartBackgroundInstance(); | 1486 RestartBackgroundInstance(); |
1441 } | 1487 } |
1442 } | 1488 } |
1443 | 1489 |
1444 #endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) | 1490 #endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) |
OLD | NEW |