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
3// found in the LICENSE file.
4
5#include "content/child/child_thread.h"
6
7#include <signal.h>
8
9#include <string>
10
11#include "base/allocator/allocator_extension.h"
12#include "base/base_switches.h"
13#include "base/basictypes.h"
14#include "base/command_line.h"
15#include "base/debug/leak_annotations.h"
16#include "base/lazy_instance.h"
17#include "base/logging.h"
18#include "base/message_loop/message_loop.h"
19#include "base/message_loop/timer_slack.h"
20#include "base/process/kill.h"
21#include "base/process/process_handle.h"
22#include "base/strings/string_number_conversions.h"
23#include "base/strings/string_util.h"
24#include "base/synchronization/condition_variable.h"
25#include "base/synchronization/lock.h"
26#include "base/threading/thread_local.h"
27#include "base/tracked_objects.h"
28#include "components/tracing/child_trace_message_filter.h"
29#include "content/child/child_histogram_message_filter.h"
30#include "content/child/child_process.h"
31#include "content/child/child_resource_message_filter.h"
32#include "content/child/child_shared_bitmap_manager.h"
33#include "content/child/fileapi/file_system_dispatcher.h"
34#include "content/child/fileapi/webfilesystem_impl.h"
35#include "content/child/mojo/mojo_application.h"
36#include "content/child/power_monitor_broadcast_source.h"
37#include "content/child/quota_dispatcher.h"
38#include "content/child/quota_message_filter.h"
39#include "content/child/resource_dispatcher.h"
40#include "content/child/service_worker/service_worker_message_filter.h"
41#include "content/child/socket_stream_dispatcher.h"
42#include "content/child/thread_safe_sender.h"
43#include "content/child/websocket_dispatcher.h"
44#include "content/common/child_process_messages.h"
45#include "content/public/common/content_switches.h"
46#include "ipc/ipc_logging.h"
47#include "ipc/ipc_switches.h"
48#include "ipc/ipc_sync_channel.h"
49#include "ipc/ipc_sync_message_filter.h"
50#include "ipc/mojo/ipc_channel_mojo.h"
51
52#if defined(OS_WIN)
53#include "content/common/handle_enumerator_win.h"
54#endif
55
56#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
57#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
58#endif
59
60using tracked_objects::ThreadData;
61
62namespace content {
63namespace {
64
65// How long to wait for a connection to the browser process before giving up.
66const int kConnectionTimeoutS = 15;
67
68base::LazyInstance<base::ThreadLocalPointer<ChildThread> > g_lazy_tls =
69    LAZY_INSTANCE_INITIALIZER;
70
71// This isn't needed on Windows because there the sandbox's job object
72// terminates child processes automatically. For unsandboxed processes (i.e.
73// plugins), PluginThread has EnsureTerminateMessageFilter.
74#if defined(OS_POSIX)
75
76// TODO(earthdok): Re-enable on CrOS http://crbug.com/360622
77#if (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
78    defined(THREAD_SANITIZER)) && !defined(OS_CHROMEOS)
79// A thread delegate that waits for |duration| and then exits the process with
80// _exit(0).
81class WaitAndExitDelegate : public base::PlatformThread::Delegate {
82 public:
83  explicit WaitAndExitDelegate(base::TimeDelta duration)
84      : duration_(duration) {}
85  virtual ~WaitAndExitDelegate() OVERRIDE {}
86
87  virtual void ThreadMain() OVERRIDE {
88    base::PlatformThread::Sleep(duration_);
89    _exit(0);
90  }
91
92 private:
93  const base::TimeDelta duration_;
94  DISALLOW_COPY_AND_ASSIGN(WaitAndExitDelegate);
95};
96
97bool CreateWaitAndExitThread(base::TimeDelta duration) {
98  scoped_ptr<WaitAndExitDelegate> delegate(new WaitAndExitDelegate(duration));
99
100  const bool thread_created =
101      base::PlatformThread::CreateNonJoinable(0, delegate.get());
102  if (!thread_created)
103    return false;
104
105  // A non joinable thread has been created. The thread will either terminate
106  // the process or will be terminated by the process. Therefore, keep the
107  // delegate object alive for the lifetime of the process.
108  WaitAndExitDelegate* leaking_delegate = delegate.release();
109  ANNOTATE_LEAKING_OBJECT_PTR(leaking_delegate);
110  ignore_result(leaking_delegate);
111  return true;
112}
113#endif
114
115class SuicideOnChannelErrorFilter : public IPC::MessageFilter {
116 public:
117  // IPC::MessageFilter
118  virtual void OnChannelError() OVERRIDE {
119    // For renderer/worker processes:
120    // On POSIX, at least, one can install an unload handler which loops
121    // forever and leave behind a renderer process which eats 100% CPU forever.
122    //
123    // This is because the terminate signals (ViewMsg_ShouldClose and the error
124    // from the IPC sender) are routed to the main message loop but never
125    // processed (because that message loop is stuck in V8).
126    //
127    // One could make the browser SIGKILL the renderers, but that leaves open a
128    // large window where a browser failure (or a user, manually terminating
129    // the browser because "it's stuck") will leave behind a process eating all
130    // the CPU.
131    //
132    // So, we install a filter on the sender so that we can process this event
133    // here and kill the process.
134    // TODO(earthdok): Re-enable on CrOS http://crbug.com/360622
135#if (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
136    defined(THREAD_SANITIZER)) && !defined(OS_CHROMEOS)
137    // Some sanitizer tools rely on exit handlers (e.g. to run leak detection,
138    // or dump code coverage data to disk). Instead of exiting the process
139    // immediately, we give it 60 seconds to run exit handlers.
140    CHECK(CreateWaitAndExitThread(base::TimeDelta::FromSeconds(60)));
141#if defined(LEAK_SANITIZER)
142    // Invoke LeakSanitizer early to avoid detecting shutdown-only leaks. If
143    // leaks are found, the process will exit here.
144    __lsan_do_leak_check();
145#endif
146#else
147    _exit(0);
148#endif
149  }
150
151 protected:
152  virtual ~SuicideOnChannelErrorFilter() {}
153};
154
155#endif  // OS(POSIX)
156
157#if defined(OS_ANDROID)
158ChildThread* g_child_thread = NULL;
159
160// A lock protects g_child_thread.
161base::LazyInstance<base::Lock> g_lazy_child_thread_lock =
162    LAZY_INSTANCE_INITIALIZER;
163
164// base::ConditionVariable has an explicit constructor that takes
165// a base::Lock pointer as parameter. The base::DefaultLazyInstanceTraits
166// doesn't handle the case. Thus, we need our own class here.
167struct CondVarLazyInstanceTraits {
168  static const bool kRegisterOnExit = true;
169#ifndef NDEBUG
170  static const bool kAllowedToAccessOnNonjoinableThread = false;
171#endif
172
173  static base::ConditionVariable* New(void* instance) {
174    return new (instance) base::ConditionVariable(
175        g_lazy_child_thread_lock.Pointer());
176  }
177  static void Delete(base::ConditionVariable* instance) {
178    instance->~ConditionVariable();
179  }
180};
181
182// A condition variable that synchronize threads initializing and waiting
183// for g_child_thread.
184base::LazyInstance<base::ConditionVariable, CondVarLazyInstanceTraits>
185    g_lazy_child_thread_cv = LAZY_INSTANCE_INITIALIZER;
186
187void QuitMainThreadMessageLoop() {
188  base::MessageLoop::current()->Quit();
189}
190
191#endif
192
193}  // namespace
194
195ChildThread::Options::Options()
196    : channel_name(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
197          switches::kProcessChannelID)),
198      use_mojo_channel(false) {}
199
200ChildThread::Options::Options(bool mojo)
201    : channel_name(base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
202          switches::kProcessChannelID)),
203      use_mojo_channel(mojo) {}
204
205
206ChildThread::ChildThreadMessageRouter::ChildThreadMessageRouter(
207    IPC::Sender* sender)
208    : sender_(sender) {}
209
210bool ChildThread::ChildThreadMessageRouter::Send(IPC::Message* msg) {
211  return sender_->Send(msg);
212}
213
214ChildThread::ChildThread()
215    : router_(this),
216      in_browser_process_(false),
217      channel_connected_factory_(this) {
218  Init(Options());
219}
220
221ChildThread::ChildThread(const Options& options)
222    : router_(this),
223      in_browser_process_(true),
224      channel_connected_factory_(this) {
225  Init(options);
226}
227
228scoped_ptr<IPC::SyncChannel> ChildThread::CreateChannel(bool use_mojo_channel) {
229  if (use_mojo_channel) {
230    VLOG(1) << "Mojo is enabled on child";
231    return IPC::SyncChannel::Create(
232        IPC::ChannelMojo::CreateClientFactory(channel_name_),
233        this,
234        ChildProcess::current()->io_message_loop_proxy(),
235        true,
236        ChildProcess::current()->GetShutDownEvent());
237  }
238
239  VLOG(1) << "Mojo is disabled on child";
240  return IPC::SyncChannel::Create(
241      channel_name_,
242      IPC::Channel::MODE_CLIENT,
243      this,
244      ChildProcess::current()->io_message_loop_proxy(),
245      true,
246      ChildProcess::current()->GetShutDownEvent());
247}
248
249void ChildThread::Init(const Options& options) {
250  channel_name_ = options.channel_name;
251
252  g_lazy_tls.Pointer()->Set(this);
253  on_channel_error_called_ = false;
254  message_loop_ = base::MessageLoop::current();
255#ifdef IPC_MESSAGE_LOG_ENABLED
256  // We must make sure to instantiate the IPC Logger *before* we create the
257  // channel, otherwise we can get a callback on the IO thread which creates
258  // the logger, and the logger does not like being created on the IO thread.
259  IPC::Logging::GetInstance();
260#endif
261  channel_ = CreateChannel(options.use_mojo_channel);
262#ifdef IPC_MESSAGE_LOG_ENABLED
263  if (!in_browser_process_)
264    IPC::Logging::GetInstance()->SetIPCSender(this);
265#endif
266
267  mojo_application_.reset(new MojoApplication);
268
269  sync_message_filter_ =
270      new IPC::SyncMessageFilter(ChildProcess::current()->GetShutDownEvent());
271  thread_safe_sender_ = new ThreadSafeSender(
272      base::MessageLoopProxy::current().get(), sync_message_filter_.get());
273
274  resource_dispatcher_.reset(new ResourceDispatcher(this));
275  socket_stream_dispatcher_.reset(new SocketStreamDispatcher());
276  websocket_dispatcher_.reset(new WebSocketDispatcher);
277  file_system_dispatcher_.reset(new FileSystemDispatcher());
278
279  histogram_message_filter_ = new ChildHistogramMessageFilter();
280  resource_message_filter_ =
281      new ChildResourceMessageFilter(resource_dispatcher());
282
283  service_worker_message_filter_ =
284      new ServiceWorkerMessageFilter(thread_safe_sender_.get());
285
286  quota_message_filter_ =
287      new QuotaMessageFilter(thread_safe_sender_.get());
288  quota_dispatcher_.reset(new QuotaDispatcher(thread_safe_sender_.get(),
289                                              quota_message_filter_.get()));
290
291  channel_->AddFilter(histogram_message_filter_.get());
292  channel_->AddFilter(sync_message_filter_.get());
293  channel_->AddFilter(resource_message_filter_.get());
294  channel_->AddFilter(quota_message_filter_->GetFilter());
295  channel_->AddFilter(service_worker_message_filter_->GetFilter());
296
297  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
298          switches::kSingleProcess)) {
299    // In single process mode, browser-side tracing will cover the whole
300    // process including renderers.
301    channel_->AddFilter(new tracing::ChildTraceMessageFilter(
302        ChildProcess::current()->io_message_loop_proxy()));
303  }
304
305  // In single process mode we may already have a power monitor
306  if (!base::PowerMonitor::Get()) {
307    scoped_ptr<PowerMonitorBroadcastSource> power_monitor_source(
308      new PowerMonitorBroadcastSource());
309    channel_->AddFilter(power_monitor_source->GetMessageFilter());
310
311    power_monitor_.reset(new base::PowerMonitor(
312        power_monitor_source.PassAs<base::PowerMonitorSource>()));
313  }
314
315#if defined(OS_POSIX)
316  // Check that --process-type is specified so we don't do this in unit tests
317  // and single-process mode.
318  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType))
319    channel_->AddFilter(new SuicideOnChannelErrorFilter());
320#endif
321
322  int connection_timeout = kConnectionTimeoutS;
323  std::string connection_override =
324      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
325          switches::kIPCConnectionTimeout);
326  if (!connection_override.empty()) {
327    int temp;
328    if (base::StringToInt(connection_override, &temp))
329      connection_timeout = temp;
330  }
331
332  base::MessageLoop::current()->PostDelayedTask(
333      FROM_HERE,
334      base::Bind(&ChildThread::EnsureConnected,
335                 channel_connected_factory_.GetWeakPtr()),
336      base::TimeDelta::FromSeconds(connection_timeout));
337
338#if defined(OS_ANDROID)
339  {
340    base::AutoLock lock(g_lazy_child_thread_lock.Get());
341    g_child_thread = this;
342  }
343  // Signalling without locking is fine here because only
344  // one thread can wait on the condition variable.
345  g_lazy_child_thread_cv.Get().Signal();
346#endif
347
348#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
349  trace_memory_controller_.reset(new base::debug::TraceMemoryController(
350      message_loop_->message_loop_proxy(),
351      ::HeapProfilerWithPseudoStackStart,
352      ::HeapProfilerStop,
353      ::GetHeapProfile));
354#endif
355
356  shared_bitmap_manager_.reset(
357      new ChildSharedBitmapManager(thread_safe_sender()));
358}
359
360ChildThread::~ChildThread() {
361#ifdef IPC_MESSAGE_LOG_ENABLED
362  IPC::Logging::GetInstance()->SetIPCSender(NULL);
363#endif
364
365  channel_->RemoveFilter(histogram_message_filter_.get());
366  channel_->RemoveFilter(sync_message_filter_.get());
367
368  // The ChannelProxy object caches a pointer to the IPC thread, so need to
369  // reset it as it's not guaranteed to outlive this object.
370  // NOTE: this also has the side-effect of not closing the main IPC channel to
371  // the browser process.  This is needed because this is the signal that the
372  // browser uses to know that this process has died, so we need it to be alive
373  // until this process is shut down, and the OS closes the handle
374  // automatically.  We used to watch the object handle on Windows to do this,
375  // but it wasn't possible to do so on POSIX.
376  channel_->ClearIPCTaskRunner();
377  g_lazy_tls.Pointer()->Set(NULL);
378}
379
380void ChildThread::Shutdown() {
381  // Delete objects that hold references to blink so derived classes can
382  // safely shutdown blink in their Shutdown implementation.
383  file_system_dispatcher_.reset();
384  quota_dispatcher_.reset();
385  WebFileSystemImpl::DeleteThreadSpecificInstance();
386}
387
388void ChildThread::OnChannelConnected(int32 peer_pid) {
389  channel_connected_factory_.InvalidateWeakPtrs();
390}
391
392void ChildThread::OnChannelError() {
393  set_on_channel_error_called(true);
394  base::MessageLoop::current()->Quit();
395}
396
397bool ChildThread::Send(IPC::Message* msg) {
398  DCHECK(base::MessageLoop::current() == message_loop());
399  if (!channel_) {
400    delete msg;
401    return false;
402  }
403
404  return channel_->Send(msg);
405}
406
407MessageRouter* ChildThread::GetRouter() {
408  DCHECK(base::MessageLoop::current() == message_loop());
409  return &router_;
410}
411
412base::SharedMemory* ChildThread::AllocateSharedMemory(size_t buf_size) {
413  return AllocateSharedMemory(buf_size, this);
414}
415
416// static
417base::SharedMemory* ChildThread::AllocateSharedMemory(
418    size_t buf_size,
419    IPC::Sender* sender) {
420  scoped_ptr<base::SharedMemory> shared_buf;
421#if defined(OS_WIN)
422  shared_buf.reset(new base::SharedMemory);
423  if (!shared_buf->CreateAndMapAnonymous(buf_size)) {
424    NOTREACHED();
425    return NULL;
426  }
427#else
428  // On POSIX, we need to ask the browser to create the shared memory for us,
429  // since this is blocked by the sandbox.
430  base::SharedMemoryHandle shared_mem_handle;
431  if (sender->Send(new ChildProcessHostMsg_SyncAllocateSharedMemory(
432                           buf_size, &shared_mem_handle))) {
433    if (base::SharedMemory::IsHandleValid(shared_mem_handle)) {
434      shared_buf.reset(new base::SharedMemory(shared_mem_handle, false));
435      if (!shared_buf->Map(buf_size)) {
436        NOTREACHED() << "Map failed";
437        return NULL;
438      }
439    } else {
440      NOTREACHED() << "Browser failed to allocate shared memory";
441      return NULL;
442    }
443  } else {
444    NOTREACHED() << "Browser allocation request message failed";
445    return NULL;
446  }
447#endif
448  return shared_buf.release();
449}
450
451bool ChildThread::OnMessageReceived(const IPC::Message& msg) {
452  if (mojo_application_->OnMessageReceived(msg))
453    return true;
454
455  // Resource responses are sent to the resource dispatcher.
456  if (resource_dispatcher_->OnMessageReceived(msg))
457    return true;
458  if (socket_stream_dispatcher_->OnMessageReceived(msg))
459    return true;
460  if (websocket_dispatcher_->OnMessageReceived(msg))
461    return true;
462  if (file_system_dispatcher_->OnMessageReceived(msg))
463    return true;
464
465  bool handled = true;
466  IPC_BEGIN_MESSAGE_MAP(ChildThread, msg)
467    IPC_MESSAGE_HANDLER(ChildProcessMsg_Shutdown, OnShutdown)
468#if defined(IPC_MESSAGE_LOG_ENABLED)
469    IPC_MESSAGE_HANDLER(ChildProcessMsg_SetIPCLoggingEnabled,
470                        OnSetIPCLoggingEnabled)
471#endif
472    IPC_MESSAGE_HANDLER(ChildProcessMsg_SetProfilerStatus,
473                        OnSetProfilerStatus)
474    IPC_MESSAGE_HANDLER(ChildProcessMsg_GetChildProfilerData,
475                        OnGetChildProfilerData)
476    IPC_MESSAGE_HANDLER(ChildProcessMsg_DumpHandles, OnDumpHandles)
477    IPC_MESSAGE_HANDLER(ChildProcessMsg_SetProcessBackgrounded,
478                        OnProcessBackgrounded)
479#if defined(USE_TCMALLOC)
480    IPC_MESSAGE_HANDLER(ChildProcessMsg_GetTcmallocStats, OnGetTcmallocStats)
481#endif
482    IPC_MESSAGE_UNHANDLED(handled = false)
483  IPC_END_MESSAGE_MAP()
484
485  if (handled)
486    return true;
487
488  if (msg.routing_id() == MSG_ROUTING_CONTROL)
489    return OnControlMessageReceived(msg);
490
491  return router_.OnMessageReceived(msg);
492}
493
494bool ChildThread::OnControlMessageReceived(const IPC::Message& msg) {
495  return false;
496}
497
498void ChildThread::OnShutdown() {
499  base::MessageLoop::current()->Quit();
500}
501
502#if defined(IPC_MESSAGE_LOG_ENABLED)
503void ChildThread::OnSetIPCLoggingEnabled(bool enable) {
504  if (enable)
505    IPC::Logging::GetInstance()->Enable();
506  else
507    IPC::Logging::GetInstance()->Disable();
508}
509#endif  //  IPC_MESSAGE_LOG_ENABLED
510
511void ChildThread::OnSetProfilerStatus(ThreadData::Status status) {
512  ThreadData::InitializeAndSetTrackingStatus(status);
513}
514
515void ChildThread::OnGetChildProfilerData(int sequence_number) {
516  tracked_objects::ProcessDataSnapshot process_data;
517  ThreadData::Snapshot(false, &process_data);
518
519  Send(new ChildProcessHostMsg_ChildProfilerData(sequence_number,
520                                                 process_data));
521}
522
523void ChildThread::OnDumpHandles() {
524#if defined(OS_WIN)
525  scoped_refptr<HandleEnumerator> handle_enum(
526      new HandleEnumerator(
527          base::CommandLine::ForCurrentProcess()->HasSwitch(
528              switches::kAuditAllHandles)));
529  handle_enum->EnumerateHandles();
530  Send(new ChildProcessHostMsg_DumpHandlesDone);
531#else
532  NOTIMPLEMENTED();
533#endif
534}
535
536#if defined(USE_TCMALLOC)
537void ChildThread::OnGetTcmallocStats() {
538  std::string result;
539  char buffer[1024 * 32];
540  base::allocator::GetStats(buffer, sizeof(buffer));
541  result.append(buffer);
542  Send(new ChildProcessHostMsg_TcmallocStats(result));
543}
544#endif
545
546ChildThread* ChildThread::current() {
547  return g_lazy_tls.Pointer()->Get();
548}
549
550#if defined(OS_ANDROID)
551// The method must NOT be called on the child thread itself.
552// It may block the child thread if so.
553void ChildThread::ShutdownThread() {
554  DCHECK(!ChildThread::current()) <<
555      "this method should NOT be called from child thread itself";
556  {
557    base::AutoLock lock(g_lazy_child_thread_lock.Get());
558    while (!g_child_thread)
559      g_lazy_child_thread_cv.Get().Wait();
560  }
561  DCHECK_NE(base::MessageLoop::current(), g_child_thread->message_loop());
562  g_child_thread->message_loop()->PostTask(
563      FROM_HERE, base::Bind(&QuitMainThreadMessageLoop));
564}
565#endif
566
567void ChildThread::OnProcessFinalRelease() {
568  if (on_channel_error_called_) {
569    base::MessageLoop::current()->Quit();
570    return;
571  }
572
573  // The child process shutdown sequence is a request response based mechanism,
574  // where we send out an initial feeler request to the child process host
575  // instance in the browser to verify if it's ok to shutdown the child process.
576  // The browser then sends back a response if it's ok to shutdown. This avoids
577  // race conditions if the process refcount is 0 but there's an IPC message
578  // inflight that would addref it.
579  Send(new ChildProcessHostMsg_ShutdownRequest);
580}
581
582void ChildThread::EnsureConnected() {
583  VLOG(0) << "ChildThread::EnsureConnected()";
584  base::KillProcess(base::GetCurrentProcessHandle(), 0, false);
585}
586
587void ChildThread::OnProcessBackgrounded(bool background) {
588  // Set timer slack to maximum on main thread when in background.
589  base::TimerSlack timer_slack = base::TIMER_SLACK_NONE;
590  if (background)
591    timer_slack = base::TIMER_SLACK_MAXIMUM;
592  base::MessageLoop::current()->SetTimerSlack(timer_slack);
593}
594
595}  // namespace content
596