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 "content/child/child_thread.h" | 5 #include "content/child/child_thread.h" |
6 | 6 |
7 #include "base/allocator/allocator_extension.h" | 7 #include "base/allocator/allocator_extension.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/lazy_instance.h" | |
9 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
10 #include "base/process.h" | 11 #include "base/process.h" |
11 #include "base/process_util.h" | 12 #include "base/process_util.h" |
12 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "base/threading/thread_local.h" | |
13 #include "base/tracked_objects.h" | 15 #include "base/tracked_objects.h" |
14 #include "components/tracing/child_trace_message_filter.h" | 16 #include "components/tracing/child_trace_message_filter.h" |
15 #include "content/child/child_histogram_message_filter.h" | 17 #include "content/child/child_histogram_message_filter.h" |
16 #include "content/child/child_process.h" | 18 #include "content/child/child_process.h" |
17 #include "content/child/child_resource_message_filter.h" | 19 #include "content/child/child_resource_message_filter.h" |
18 #include "content/child/fileapi/file_system_dispatcher.h" | 20 #include "content/child/fileapi/file_system_dispatcher.h" |
19 #include "content/child/quota_dispatcher.h" | 21 #include "content/child/quota_dispatcher.h" |
20 #include "content/child/resource_dispatcher.h" | 22 #include "content/child/resource_dispatcher.h" |
21 #include "content/child/socket_stream_dispatcher.h" | 23 #include "content/child/socket_stream_dispatcher.h" |
22 #include "content/child/thread_safe_sender.h" | 24 #include "content/child/thread_safe_sender.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
33 #endif | 35 #endif |
34 | 36 |
35 using tracked_objects::ThreadData; | 37 using tracked_objects::ThreadData; |
36 | 38 |
37 namespace content { | 39 namespace content { |
38 namespace { | 40 namespace { |
39 | 41 |
40 // How long to wait for a connection to the browser process before giving up. | 42 // How long to wait for a connection to the browser process before giving up. |
41 const int kConnectionTimeoutS = 15; | 43 const int kConnectionTimeoutS = 15; |
42 | 44 |
45 base::LazyInstance<base::ThreadLocalPointer<ChildThread> > g_lazy_tls = | |
46 LAZY_INSTANCE_INITIALIZER; | |
47 | |
43 // This isn't needed on Windows because there the sandbox's job object | 48 // This isn't needed on Windows because there the sandbox's job object |
44 // terminates child processes automatically. For unsandboxed processes (i.e. | 49 // terminates child processes automatically. For unsandboxed processes (i.e. |
45 // plugins), PluginThread has EnsureTerminateMessageFilter. | 50 // plugins), PluginThread has EnsureTerminateMessageFilter. |
46 #if defined(OS_POSIX) | 51 #if defined(OS_POSIX) |
47 | 52 |
48 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { | 53 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { |
49 public: | 54 public: |
50 // IPC::ChannelProxy::MessageFilter | 55 // IPC::ChannelProxy::MessageFilter |
51 virtual void OnChannelError() OVERRIDE { | 56 virtual void OnChannelError() OVERRIDE { |
52 // For renderer/worker processes: | 57 // For renderer/worker processes: |
(...skipping 20 matching lines...) Expand all Loading... | |
73 else | 78 else |
74 _exit(0); | 79 _exit(0); |
75 } | 80 } |
76 | 81 |
77 protected: | 82 protected: |
78 virtual ~SuicideOnChannelErrorFilter() {} | 83 virtual ~SuicideOnChannelErrorFilter() {} |
79 }; | 84 }; |
80 | 85 |
81 #endif // OS(POSIX) | 86 #endif // OS(POSIX) |
82 | 87 |
88 #if defined(OS_ANDROID) | |
89 ChildThread* g_child_thread; | |
Feng Qian
2013/06/28 17:12:14
@jam, won't this be a race condition when both Ren
jam
2013/07/01 19:29:26
this is only called by content/app/android/child_p
| |
90 | |
91 void QuitMainThreadMessageLoop() { | |
92 base::MessageLoop::current()->Quit(); | |
93 } | |
94 | |
95 #endif | |
96 | |
83 } // namespace | 97 } // namespace |
84 | 98 |
85 ChildThread::ChildThread() | 99 ChildThread::ChildThread() |
86 : channel_connected_factory_(this) { | 100 : channel_connected_factory_(this) { |
87 channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 101 channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
88 switches::kProcessChannelID); | 102 switches::kProcessChannelID); |
89 Init(); | 103 Init(); |
90 } | 104 } |
91 | 105 |
92 ChildThread::ChildThread(const std::string& channel_name) | 106 ChildThread::ChildThread(const std::string& channel_name) |
93 : channel_name_(channel_name), | 107 : channel_name_(channel_name), |
94 channel_connected_factory_(this) { | 108 channel_connected_factory_(this) { |
95 Init(); | 109 Init(); |
96 } | 110 } |
97 | 111 |
98 void ChildThread::Init() { | 112 void ChildThread::Init() { |
113 g_lazy_tls.Pointer()->Set(this); | |
99 on_channel_error_called_ = false; | 114 on_channel_error_called_ = false; |
100 message_loop_ = base::MessageLoop::current(); | 115 message_loop_ = base::MessageLoop::current(); |
101 channel_.reset( | 116 channel_.reset( |
102 new IPC::SyncChannel(channel_name_, | 117 new IPC::SyncChannel(channel_name_, |
103 IPC::Channel::MODE_CLIENT, | 118 IPC::Channel::MODE_CLIENT, |
104 this, | 119 this, |
105 ChildProcess::current()->io_message_loop_proxy(), | 120 ChildProcess::current()->io_message_loop_proxy(), |
106 true, | 121 true, |
107 ChildProcess::current()->GetShutDownEvent())); | 122 ChildProcess::current()->GetShutDownEvent())); |
108 #ifdef IPC_MESSAGE_LOG_ENABLED | 123 #ifdef IPC_MESSAGE_LOG_ENABLED |
(...skipping 24 matching lines...) Expand all Loading... | |
133 // and single-process mode. | 148 // and single-process mode. |
134 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType)) | 149 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType)) |
135 channel_->AddFilter(new SuicideOnChannelErrorFilter()); | 150 channel_->AddFilter(new SuicideOnChannelErrorFilter()); |
136 #endif | 151 #endif |
137 | 152 |
138 base::MessageLoop::current()->PostDelayedTask( | 153 base::MessageLoop::current()->PostDelayedTask( |
139 FROM_HERE, | 154 FROM_HERE, |
140 base::Bind(&ChildThread::EnsureConnected, | 155 base::Bind(&ChildThread::EnsureConnected, |
141 channel_connected_factory_.GetWeakPtr()), | 156 channel_connected_factory_.GetWeakPtr()), |
142 base::TimeDelta::FromSeconds(kConnectionTimeoutS)); | 157 base::TimeDelta::FromSeconds(kConnectionTimeoutS)); |
158 | |
159 #if defined(OS_ANDROID) | |
160 g_child_thread = this; | |
161 #endif | |
143 } | 162 } |
144 | 163 |
145 ChildThread::~ChildThread() { | 164 ChildThread::~ChildThread() { |
146 #ifdef IPC_MESSAGE_LOG_ENABLED | 165 #ifdef IPC_MESSAGE_LOG_ENABLED |
147 IPC::Logging::GetInstance()->SetIPCSender(NULL); | 166 IPC::Logging::GetInstance()->SetIPCSender(NULL); |
148 #endif | 167 #endif |
149 | 168 |
150 channel_->RemoveFilter(histogram_message_filter_.get()); | 169 channel_->RemoveFilter(histogram_message_filter_.get()); |
151 channel_->RemoveFilter(sync_message_filter_.get()); | 170 channel_->RemoveFilter(sync_message_filter_.get()); |
152 | 171 |
153 // The ChannelProxy object caches a pointer to the IPC thread, so need to | 172 // The ChannelProxy object caches a pointer to the IPC thread, so need to |
154 // reset it as it's not guaranteed to outlive this object. | 173 // reset it as it's not guaranteed to outlive this object. |
155 // NOTE: this also has the side-effect of not closing the main IPC channel to | 174 // NOTE: this also has the side-effect of not closing the main IPC channel to |
156 // the browser process. This is needed because this is the signal that the | 175 // the browser process. This is needed because this is the signal that the |
157 // browser uses to know that this process has died, so we need it to be alive | 176 // browser uses to know that this process has died, so we need it to be alive |
158 // until this process is shut down, and the OS closes the handle | 177 // until this process is shut down, and the OS closes the handle |
159 // automatically. We used to watch the object handle on Windows to do this, | 178 // automatically. We used to watch the object handle on Windows to do this, |
160 // but it wasn't possible to do so on POSIX. | 179 // but it wasn't possible to do so on POSIX. |
161 channel_->ClearIPCTaskRunner(); | 180 channel_->ClearIPCTaskRunner(); |
181 g_lazy_tls.Pointer()->Set(NULL); | |
162 } | 182 } |
163 | 183 |
164 void ChildThread::OnChannelConnected(int32 peer_pid) { | 184 void ChildThread::OnChannelConnected(int32 peer_pid) { |
165 channel_connected_factory_.InvalidateWeakPtrs(); | 185 channel_connected_factory_.InvalidateWeakPtrs(); |
166 } | 186 } |
167 | 187 |
168 void ChildThread::OnChannelError() { | 188 void ChildThread::OnChannelError() { |
169 set_on_channel_error_called(true); | 189 set_on_channel_error_called(true); |
170 base::MessageLoop::current()->Quit(); | 190 base::MessageLoop::current()->Quit(); |
171 } | 191 } |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
321 void ChildThread::OnGetTcmallocStats() { | 341 void ChildThread::OnGetTcmallocStats() { |
322 std::string result; | 342 std::string result; |
323 char buffer[1024 * 32]; | 343 char buffer[1024 * 32]; |
324 base::allocator::GetStats(buffer, sizeof(buffer)); | 344 base::allocator::GetStats(buffer, sizeof(buffer)); |
325 result.append(buffer); | 345 result.append(buffer); |
326 Send(new ChildProcessHostMsg_TcmallocStats(result)); | 346 Send(new ChildProcessHostMsg_TcmallocStats(result)); |
327 } | 347 } |
328 #endif | 348 #endif |
329 | 349 |
330 ChildThread* ChildThread::current() { | 350 ChildThread* ChildThread::current() { |
331 return ChildProcess::current() ? | 351 return g_lazy_tls.Pointer()->Get(); |
332 ChildProcess::current()->main_thread() : NULL; | |
333 } | 352 } |
334 | 353 |
335 bool ChildThread::IsWebFrameValid(WebKit::WebFrame* frame) { | 354 #if defined(OS_ANDROID) |
336 // Return false so that it is overridden in any process in which it is used. | 355 void ChildThread::ShutdownThread() { |
337 return false; | 356 DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop()); |
357 g_child_thread->message_loop()->PostTask( | |
358 FROM_HERE, base::Bind(&QuitMainThreadMessageLoop)); | |
338 } | 359 } |
339 | 360 |
361 #endif | |
362 | |
340 void ChildThread::OnProcessFinalRelease() { | 363 void ChildThread::OnProcessFinalRelease() { |
341 if (on_channel_error_called_) { | 364 if (on_channel_error_called_) { |
342 base::MessageLoop::current()->Quit(); | 365 base::MessageLoop::current()->Quit(); |
343 return; | 366 return; |
344 } | 367 } |
345 | 368 |
346 // The child process shutdown sequence is a request response based mechanism, | 369 // The child process shutdown sequence is a request response based mechanism, |
347 // where we send out an initial feeler request to the child process host | 370 // where we send out an initial feeler request to the child process host |
348 // instance in the browser to verify if it's ok to shutdown the child process. | 371 // instance in the browser to verify if it's ok to shutdown the child process. |
349 // The browser then sends back a response if it's ok to shutdown. This avoids | 372 // The browser then sends back a response if it's ok to shutdown. This avoids |
350 // race conditions if the process refcount is 0 but there's an IPC message | 373 // race conditions if the process refcount is 0 but there's an IPC message |
351 // inflight that would addref it. | 374 // inflight that would addref it. |
352 Send(new ChildProcessHostMsg_ShutdownRequest); | 375 Send(new ChildProcessHostMsg_ShutdownRequest); |
353 } | 376 } |
354 | 377 |
355 void ChildThread::EnsureConnected() { | 378 void ChildThread::EnsureConnected() { |
356 LOG(INFO) << "ChildThread::EnsureConnected()"; | 379 LOG(INFO) << "ChildThread::EnsureConnected()"; |
357 base::KillProcess(base::GetCurrentProcessHandle(), 0, false); | 380 base::KillProcess(base::GetCurrentProcessHandle(), 0, false); |
358 } | 381 } |
359 | 382 |
360 } // namespace content | 383 } // namespace content |
OLD | NEW |