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

Unified Diff: content/browser/browser_main_loop.cc

Issue 8477004: Have content/ create and destroy its own threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: With this patchset, Chrome runs and exits normally on Linux. Created 9 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/browser_main_loop.cc
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 97da69ea79747081835c8d661897dd20bb346a8e..ad9871d06ba73c53b5d1d9603f06280b34200db9 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -262,8 +262,50 @@ void BrowserMainLoop::MainMessageLoopStart() {
void BrowserMainLoop::RunMainMessageLoopParts(
bool* completed_main_message_loop) {
+ IOThreadDelegate* io_thread_delegate = NULL;
+ for (size_t i = 0; i < parts_list_.size(); ++i) {
+ IOThreadDelegate* current_delegate =
+ parts_list_[i]->PreMainMessageLoopRun();
+ if (current_delegate) {
+ DCHECK(!io_thread_delegate) << "Only one delegate allowed.";
+ io_thread_delegate = current_delegate;
+ }
+ }
+
+ base::Thread::Options io_message_loop_options;
+ io_message_loop_options.message_loop_type = MessageLoop::TYPE_IO;
+ base::Thread::Options ui_message_loop_options;
+ ui_message_loop_options.message_loop_type = MessageLoop::TYPE_UI;
+
+ db_thread_.reset(new BrowserProcessSubThread(BrowserThread::DB));
+ db_thread_->Start();
+
+ file_thread_.reset(new BrowserProcessSubThread(BrowserThread::FILE));
+#if defined(OS_WIN)
+ // On Windows, the FILE thread needs to be have a UI message loop
+ // which pumps messages in such a way that Google Update can
+ // communicate back to us.
+ file_thread_->StartWithOptions(ui_message_loop_options);
+#else
+ file_thread_->StartWithOptions(io_message_loop_options);
+#endif
+
+ process_launcher_thread_.reset(
+ new BrowserProcessSubThread(BrowserThread::PROCESS_LAUNCHER));
+ process_launcher_thread_->Start();
+
+ cache_thread_.reset(new BrowserProcessSubThread(BrowserThread::CACHE));
+ cache_thread_->StartWithOptions(io_message_loop_options);
+ io_thread_.reset(new BrowserProcessIOThread(io_thread_delegate));
+ io_thread_->StartWithOptions(io_message_loop_options);
+#if defined(OS_CHROMEOS)
+ web_socket_proxy_thread_.reset(
+ new BrowserProcessSubThread(BrowserThread::WEB_SOCKET_PROXY));
+ web_socket_proxy_thread_->StartWithOptions(io_message_loop_options);
+#endif
+
for (size_t i = 0; i < parts_list_.size(); ++i)
- parts_list_[i]->PreMainMessageLoopRun();
+ parts_list_[i]->PreMainMessageLoopRunThreadsCreated();
TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
// If the UI thread blocks, the whole UI is unresponsive.
@@ -289,8 +331,91 @@ void BrowserMainLoop::RunMainMessageLoopParts(
if (completed_main_message_loop)
*completed_main_message_loop = true;
+ // Teardown may start in PostMainMessageLoopRun, and during teardown we
+ // need to be able to perform IO.
+ base::ThreadRestrictions::SetIOAllowed(true);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ NewRunnableFunction(&base::ThreadRestrictions::SetIOAllowed, true));
+
for (size_t i = 0; i < parts_list_.size(); ++i)
parts_list_[i]->PostMainMessageLoopRun();
+
+ // Must be size_t so we can subtract from it.
+ for (size_t thread_id = BrowserThread::ID_COUNT - 1;
+ thread_id >= BrowserThread::DB;
+ --thread_id) {
+ // Find the thread object we want to stop. Looping over all valid
+ // BrowserThread IDs and DCHECKing on a missing case in the switch
+ // statement helps avoid a mismatch between this code and the
+ // BrowserThread::ID enumeration.
+ //
+ // The destruction order is the reverse order of occurrence in the
+ // BrowserThread::ID list. The rationale for the order is as
+ // follows (need to be filled in a bit):
+ //
+ // - (Not sure why the WEB_SOCKET_PROXY thread is stopped first.)
+ //
+ // - The IO thread is the only user of the CACHE thread.
+ //
+ // - The PROCESS_LAUNCHER thread must be stopped after IO in case
+ // the IO thread posted a task to terminate a process on the
+ // process launcher thread.
+ //
+ // - (Not sure why FILE needs to stop before WEBKIT.)
+ //
+ // - The WEBKIT thread (which currently is the responsibility of
+ // the embedder to stop, by destroying ResourceDispatcherHost
+ // before the DB thread is stopped)
+ //
+ // - (Not sure why DB stops last.)
+ scoped_ptr<BrowserProcessSubThread>* thread_to_stop = NULL;
+ switch (thread_id) {
+ case BrowserThread::UI:
+ case BrowserThread::ID_COUNT:
+ NOTREACHED();
+ break;
+ case BrowserThread::DB:
+ thread_to_stop = &db_thread_;
+ break;
+ case BrowserThread::WEBKIT:
+ // For now, the WebKit thread in the browser is owned by
+ // ResourceDispatcherHost, not by the content framework. Until
+ // this is fixed, we don't stop the thread but still call
+ // Pre/PostStopThread for the ID.
+ break;
+ case BrowserThread::FILE:
+ thread_to_stop = &file_thread_;
+ break;
+ case BrowserThread::PROCESS_LAUNCHER:
+ thread_to_stop = &process_launcher_thread_;
+ break;
+ case BrowserThread::CACHE:
+ thread_to_stop = &cache_thread_;
+ break;
+ case BrowserThread::IO:
+ thread_to_stop = &io_thread_;
+ break;
+#if defined(OS_CHROMEOS)
+ case BrowserThread::WEB_SOCKET_PROXY:
+ thread_to_stop = &web_socket_proxy_thread_;
+ break;
+#endif
+ }
+
+ BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id);
+
+ for (size_t i = 0; i < parts_list_.size(); ++i)
+ parts_list_[i]->PreStopThread(id);
+ if (thread_to_stop)
+ thread_to_stop->reset();
+ for (size_t i = 0; i < parts_list_.size(); ++i)
+ parts_list_[i]->PostStopThread(id);
+ }
+
+ for (size_t i = 0; i < parts_list_.size(); ++i)
+ parts_list_[i]->FinalCleanup();
}
void BrowserMainLoop::InitializeMainThread() {

Powered by Google App Engine
This is Rietveld 408576698