diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-20 22:20:20 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-20 22:20:20 +0000 |
commit | f717ea6403554cc60a5dd9312fe585cdf64a8815 (patch) | |
tree | 523186875fe4c36bcc1c6905b3da36943a174318 /chrome/common | |
parent | e74b81de4f2785b5cff5cb0cc85e76b3d434248e (diff) | |
download | chromium_src-f717ea6403554cc60a5dd9312fe585cdf64a8815.zip chromium_src-f717ea6403554cc60a5dd9312fe585cdf64a8815.tar.gz chromium_src-f717ea6403554cc60a5dd9312fe585cdf64a8815.tar.bz2 |
Switch the first thread in a child process to be the main thread, and make the IO thread be the second thread. The change is needed for plugins on mac.
Review URL: http://codereview.chromium.org/149558
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21117 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r-- | chrome/common/child_process.cc | 27 | ||||
-rw-r--r-- | chrome/common/child_process.h | 28 | ||||
-rw-r--r-- | chrome/common/child_thread.cc | 72 | ||||
-rw-r--r-- | chrome/common/child_thread.h | 38 | ||||
-rw-r--r-- | chrome/common/histogram_synchronizer.cc | 1 | ||||
-rw-r--r-- | chrome/common/ipc_channel_proxy.cc | 4 | ||||
-rw-r--r-- | chrome/common/ipc_channel_proxy.h | 4 |
7 files changed, 85 insertions, 89 deletions
diff --git a/chrome/common/child_process.cc b/chrome/common/child_process.cc index f32708c..b777ff2 100644 --- a/chrome/common/child_process.cc +++ b/chrome/common/child_process.cc @@ -9,14 +9,14 @@ ChildProcess* ChildProcess::child_process_; -ChildProcess::ChildProcess(ChildThread* child_thread) - : child_thread_(child_thread), - ref_count_(0), - shutdown_event_(true, false) { +ChildProcess::ChildProcess() + : ref_count_(0), + shutdown_event_(true, false), + io_thread_("Chrome_ChildIOThread") { DCHECK(!child_process_); child_process_ = this; - if (child_thread_.get()) // null in unittests. - child_thread_->Run(); + + io_thread_.StartWithOptions(base::Thread::Options(MessageLoop::TYPE_IO, 0)); } ChildProcess::~ChildProcess() { @@ -28,28 +28,25 @@ ChildProcess::~ChildProcess() { // notice shutdown before the render process begins waiting for them to exit. shutdown_event_.Signal(); - if (child_thread_.get()) - child_thread_->Stop(); - child_process_ = NULL; } void ChildProcess::AddRefProcess() { - DCHECK(!child_thread_.get() || // null in unittests. - MessageLoop::current() == child_thread_->message_loop()); + DCHECK(!main_thread_.get() || // null in unittests. + MessageLoop::current() == main_thread_->message_loop()); ref_count_++; } void ChildProcess::ReleaseProcess() { - DCHECK(!child_thread_.get() || // null in unittests. - MessageLoop::current() == child_thread_->message_loop()); + DCHECK(!main_thread_.get() || // null in unittests. + MessageLoop::current() == main_thread_->message_loop()); DCHECK(ref_count_); DCHECK(child_process_); if (--ref_count_) return; - if (child_thread_.get()) // null in unittests. - child_thread_->OnProcessFinalRelease(); + if (main_thread_.get()) // null in unittests. + main_thread_->OnProcessFinalRelease(); } base::WaitableEvent* ChildProcess::GetShutDownEvent() { diff --git a/chrome/common/child_process.h b/chrome/common/child_process.h index 1366a02..5e125bc 100644 --- a/chrome/common/child_process.h +++ b/chrome/common/child_process.h @@ -7,21 +7,23 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" +#include "base/thread.h" #include "base/waitable_event.h" - -class ChildThread; +#include "chrome/common/child_thread.h" // Base class for child processes of the browser process (i.e. renderer and // plugin host). This is a singleton object for each child process. class ChildProcess { public: - // Child processes should have an object that derives from this class. The - // constructor will return once ChildThread has started. - ChildProcess(ChildThread* child_thread); + // Child processes should have an object that derives from this class. + ChildProcess(); virtual ~ChildProcess(); - // Getter for this process' main thread. - ChildThread* child_thread() { return child_thread_.get(); } + // Getter for the child process' main thread. + ChildThread* main_thread() { return main_thread_.get(); } + void set_main_thread(ChildThread* thread) { main_thread_.reset(thread); } + + MessageLoop* io_message_loop() { return io_thread_.message_loop(); } // A global event object that is signalled when the main thread's message // loop exits. This gives background threads a way to observe the main @@ -45,15 +47,19 @@ class ChildProcess { static ChildProcess* current() { return child_process_; } private: - // NOTE: make sure that child_thread_ is listed before shutdown_event_, since - // it depends on it (indirectly through IPC::SyncChannel). - scoped_ptr<ChildThread> child_thread_; - int ref_count_; // An event that will be signalled when we shutdown. base::WaitableEvent shutdown_event_; + // The thread that handles IO events. + base::Thread io_thread_; + + // NOTE: make sure that main_thread_ is listed after shutdown_event_, since + // it depends on it (indirectly through IPC::SyncChannel). Same for + // io_thread_. + scoped_ptr<ChildThread> main_thread_; + // The singleton instance for this process. static ChildProcess* child_process_; diff --git a/chrome/common/child_thread.cc b/chrome/common/child_thread.cc index 4c97b72..db3c4c5 100644 --- a/chrome/common/child_thread.cc +++ b/chrome/common/child_thread.cc @@ -9,19 +9,14 @@ #include "chrome/common/child_process.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/ipc_logging.h" +#include "chrome/common/notification_service.h" #include "chrome/common/plugin_messages.h" #include "webkit/glue/webkit_glue.h" -// V8 needs a 1MB stack size. -const size_t ChildThread::kV8StackSize = 1024 * 1024; - -ChildThread::ChildThread(Thread::Options options) - : Thread("Chrome_ChildThread"), - owner_loop_(MessageLoop::current()), - options_(options), - check_with_browser_before_shutdown_(false) { - DCHECK(owner_loop_); +ChildThread::ChildThread() + : check_with_browser_before_shutdown_(false), + message_loop_(MessageLoop::current()) { channel_name_ = WideToASCII( CommandLine::ForCurrentProcess()->GetSwitchValue( switches::kProcessChannelID)); @@ -31,17 +26,41 @@ ChildThread::ChildThread(Thread::Options options) CommandLine::ForCurrentProcess()->GetSwitchValue( switches::kUserAgent))); } + + channel_.reset(new IPC::SyncChannel(channel_name_, + IPC::Channel::MODE_CLIENT, this, NULL, + ChildProcess::current()->io_message_loop(), true, + ChildProcess::current()->GetShutDownEvent())); +#ifdef IPC_MESSAGE_LOG_ENABLED + IPC::Logging::current()->SetIPCSender(this); +#endif + + resource_dispatcher_.reset(new ResourceDispatcher(this)); + + // When running in unit tests, there is already a NotificationService object. + // Since only one can exist at a time per thread, check first. + if (!NotificationService::current()) + notification_service_.reset(new NotificationService); } ChildThread::~ChildThread() { -} +#ifdef IPC_MESSAGE_LOG_ENABLED + IPC::Logging::current()->SetIPCSender(NULL); +#endif -bool ChildThread::Run() { - return StartWithOptions(options_); + // The ChannelProxy object caches a pointer to the IPC thread, so need to + // reset it as it's not guaranteed to outlive this object. + // NOTE: this also has the side-effect of not closing the main IPC channel to + // the browser process. This is needed because this is the signal that the + // browser uses to know that this process has died, so we need it to be alive + // until this process is shut down, and the OS closes the handle + // automatically. We used to watch the object handle on Windows to do this, + // but it wasn't possible to do so on POSIX. + channel_->ClearIPCMessageLoop(); } void ChildThread::OnChannelError() { - owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); + MessageLoop::current()->Quit(); } bool ChildThread::Send(IPC::Message* msg) { @@ -76,7 +95,7 @@ void ChildThread::OnMessageReceived(const IPC::Message& msg) { } if (msg.type() == PluginProcessMsg_Shutdown::ID) { - owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); + MessageLoop::current()->Quit(); return; } @@ -88,33 +107,12 @@ void ChildThread::OnMessageReceived(const IPC::Message& msg) { } ChildThread* ChildThread::current() { - return ChildProcess::current()->child_thread(); -} - -void ChildThread::Init() { - channel_.reset(new IPC::SyncChannel(channel_name_, - IPC::Channel::MODE_CLIENT, this, NULL, owner_loop_, true, - ChildProcess::current()->GetShutDownEvent())); -#ifdef IPC_MESSAGE_LOG_ENABLED - IPC::Logging::current()->SetIPCSender(this); -#endif - - resource_dispatcher_.reset(new ResourceDispatcher(this)); -} - -void ChildThread::CleanUp() { -#ifdef IPC_MESSAGE_LOG_ENABLED - IPC::Logging::current()->SetIPCSender(NULL); -#endif - // Need to destruct the SyncChannel to the browser before we go away because - // it caches a pointer to this thread. - channel_.reset(); - resource_dispatcher_.reset(); + return ChildProcess::current()->main_thread(); } void ChildThread::OnProcessFinalRelease() { if (!check_with_browser_before_shutdown_) { - owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask()); + MessageLoop::current()->Quit(); return; } diff --git a/chrome/common/child_thread.h b/chrome/common/child_thread.h index cc4abaa..86eae4c 100644 --- a/chrome/common/child_thread.h +++ b/chrome/common/child_thread.h @@ -7,18 +7,18 @@ #include "base/basictypes.h" #include "base/scoped_ptr.h" -#include "base/thread.h" #include "chrome/common/ipc_sync_channel.h" #include "chrome/common/message_router.h" #include "chrome/common/resource_dispatcher.h" -// Child processes's background thread should derive from this class. +class NotificationService; + +// The main thread of a child process derives from this class. class ChildThread : public IPC::Channel::Listener, - public IPC::Message::Sender, - public base::Thread { + public IPC::Message::Sender { public: // Creates the thread. - ChildThread(Thread::Options options); + ChildThread(); virtual ~ChildThread(); // IPC::Message::Sender implementation: @@ -28,58 +28,40 @@ class ChildThread : public IPC::Channel::Listener, void AddRoute(int32 routing_id, IPC::Channel::Listener* listener); void RemoveRoute(int32 routing_id); - MessageLoop* owner_loop() { return owner_loop_; } - ResourceDispatcher* resource_dispatcher() { return resource_dispatcher_.get(); } + MessageLoop* message_loop() { return message_loop_; } + // Returns the one child thread. static ChildThread* current(); protected: friend class ChildProcess; - // Starts the thread. - bool Run(); - // Overrides the channel name. Used for --single-process mode. void SetChannelName(const std::string& name) { channel_name_ = name; } // Called when the process refcount is 0. void OnProcessFinalRelease(); - protected: - // The required stack size if V8 runs on a thread. - static const size_t kV8StackSize; - virtual void OnControlMessageReceived(const IPC::Message& msg) { } IPC::SyncChannel* channel() { return channel_.get(); } - // Thread implementation. - virtual void Init(); - virtual void CleanUp(); - private: // IPC::Channel::Listener implementation: virtual void OnMessageReceived(const IPC::Message& msg); virtual void OnChannelError(); - // The message loop used to run tasks on the thread that started this thread. - MessageLoop* owner_loop_; - std::string channel_name_; scoped_ptr<IPC::SyncChannel> channel_; - // Used only on the background render thread to implement message routing - // functionality to the consumers of the ChildThread. + // Implements message routing functionality to the consumers of ChildThread. MessageRouter router_; - Thread::Options options_; - // Handles resource loads for this process. - // NOTE: this object lives on the owner thread. scoped_ptr<ResourceDispatcher> resource_dispatcher_; // If true, checks with the browser process before shutdown. This avoids race @@ -87,6 +69,10 @@ class ChildThread : public IPC::Channel::Listener, // that would addref it. bool check_with_browser_before_shutdown_; + MessageLoop* message_loop_; + + scoped_ptr<NotificationService> notification_service_; + DISALLOW_COPY_AND_ASSIGN(ChildThread); }; diff --git a/chrome/common/histogram_synchronizer.cc b/chrome/common/histogram_synchronizer.cc index 4713084..9ed94b0 100644 --- a/chrome/common/histogram_synchronizer.cc +++ b/chrome/common/histogram_synchronizer.cc @@ -7,6 +7,7 @@ #include "base/histogram.h" #include "base/logging.h" #include "base/string_util.h" +#include "base/thread.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" diff --git a/chrome/common/ipc_channel_proxy.cc b/chrome/common/ipc_channel_proxy.cc index c97e6f5..eedca7e 100644 --- a/chrome/common/ipc_channel_proxy.cc +++ b/chrome/common/ipc_channel_proxy.cc @@ -272,6 +272,10 @@ void ChannelProxy::RemoveFilter(MessageFilter* filter) { context_.get(), &Context::OnRemoveFilter, filter)); } +void ChannelProxy::ClearIPCMessageLoop() { + context()->ClearIPCMessageLoop(); +} + #if defined(OS_POSIX) // See the TODO regarding lazy initialization of the channel in // ChannelProxy::Init(). diff --git a/chrome/common/ipc_channel_proxy.h b/chrome/common/ipc_channel_proxy.h index 8adcb5b..3725ab1 100644 --- a/chrome/common/ipc_channel_proxy.h +++ b/chrome/common/ipc_channel_proxy.h @@ -117,6 +117,9 @@ class ChannelProxy : public Message::Sender { void AddFilter(MessageFilter* filter); void RemoveFilter(MessageFilter* filter); + // Called to clear the pointer to the IPC message loop when it's going away. + void ClearIPCMessageLoop(); + #if defined(OS_POSIX) // Calls through to the underlying channel's methods. // TODO(playmobil): For now this is only implemented in the case of @@ -140,6 +143,7 @@ class ChannelProxy : public Message::Sender { Context(Channel::Listener* listener, MessageFilter* filter, MessageLoop* ipc_thread); virtual ~Context() { } + void ClearIPCMessageLoop() { ipc_message_loop_ = NULL; } MessageLoop* ipc_message_loop() const { return ipc_message_loop_; } const std::string& channel_id() const { return channel_id_; } |