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 <signal.h> | 7 #include <signal.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 const int kConnectionTimeoutS = 15; | 63 const int kConnectionTimeoutS = 15; |
64 | 64 |
65 base::LazyInstance<base::ThreadLocalPointer<ChildThread> > g_lazy_tls = | 65 base::LazyInstance<base::ThreadLocalPointer<ChildThread> > g_lazy_tls = |
66 LAZY_INSTANCE_INITIALIZER; | 66 LAZY_INSTANCE_INITIALIZER; |
67 | 67 |
68 // This isn't needed on Windows because there the sandbox's job object | 68 // This isn't needed on Windows because there the sandbox's job object |
69 // terminates child processes automatically. For unsandboxed processes (i.e. | 69 // terminates child processes automatically. For unsandboxed processes (i.e. |
70 // plugins), PluginThread has EnsureTerminateMessageFilter. | 70 // plugins), PluginThread has EnsureTerminateMessageFilter. |
71 #if defined(OS_POSIX) | 71 #if defined(OS_POSIX) |
72 | 72 |
| 73 // TODO(earthdok): Re-enable on CrOS http://crbug.com/360622 |
| 74 #if (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ |
| 75 defined(THREAD_SANITIZER)) && !defined(OS_CHROMEOS) |
| 76 // A thread delegate that waits for |duration| and then exits the process with |
| 77 // _exit(0). |
| 78 class WaitAndExitDelegate : public base::PlatformThread::Delegate { |
| 79 public: |
| 80 explicit WaitAndExitDelegate(base::TimeDelta duration) |
| 81 : duration_(duration) {} |
| 82 virtual ~WaitAndExitDelegate() OVERRIDE {} |
| 83 |
| 84 virtual void ThreadMain() OVERRIDE { |
| 85 base::PlatformThread::Sleep(duration_); |
| 86 _exit(0); |
| 87 } |
| 88 |
| 89 private: |
| 90 const base::TimeDelta duration_; |
| 91 DISALLOW_COPY_AND_ASSIGN(WaitAndExitDelegate); |
| 92 }; |
| 93 |
| 94 bool CreateWaitAndExitThread(base::TimeDelta duration) { |
| 95 scoped_ptr<WaitAndExitDelegate> delegate(new WaitAndExitDelegate(duration)); |
| 96 |
| 97 const bool thread_created = |
| 98 base::PlatformThread::CreateNonJoinable(0, delegate.get()); |
| 99 if (!thread_created) |
| 100 return false; |
| 101 |
| 102 // A non joinable thread has been created. The thread will either terminate |
| 103 // the process or will be terminated by the process. Therefore, keep the |
| 104 // delegate object alive for the lifetime of the process. |
| 105 WaitAndExitDelegate* leaking_delegate = delegate.release(); |
| 106 ANNOTATE_LEAKING_OBJECT_PTR(leaking_delegate); |
| 107 ignore_result(leaking_delegate); |
| 108 return true; |
| 109 } |
| 110 #endif |
| 111 |
73 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { | 112 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { |
74 public: | 113 public: |
75 // IPC::ChannelProxy::MessageFilter | 114 // IPC::ChannelProxy::MessageFilter |
76 virtual void OnChannelError() OVERRIDE { | 115 virtual void OnChannelError() OVERRIDE { |
77 // For renderer/worker processes: | 116 // For renderer/worker processes: |
78 // On POSIX, at least, one can install an unload handler which loops | 117 // On POSIX, at least, one can install an unload handler which loops |
79 // forever and leave behind a renderer process which eats 100% CPU forever. | 118 // forever and leave behind a renderer process which eats 100% CPU forever. |
80 // | 119 // |
81 // This is because the terminate signals (ViewMsg_ShouldClose and the error | 120 // This is because the terminate signals (ViewMsg_ShouldClose and the error |
82 // from the IPC channel) are routed to the main message loop but never | 121 // from the IPC channel) are routed to the main message loop but never |
83 // processed (because that message loop is stuck in V8). | 122 // processed (because that message loop is stuck in V8). |
84 // | 123 // |
85 // One could make the browser SIGKILL the renderers, but that leaves open a | 124 // One could make the browser SIGKILL the renderers, but that leaves open a |
86 // large window where a browser failure (or a user, manually terminating | 125 // large window where a browser failure (or a user, manually terminating |
87 // the browser because "it's stuck") will leave behind a process eating all | 126 // the browser because "it's stuck") will leave behind a process eating all |
88 // the CPU. | 127 // the CPU. |
89 // | 128 // |
90 // So, we install a filter on the channel so that we can process this event | 129 // So, we install a filter on the channel so that we can process this event |
91 // here and kill the process. | 130 // here and kill the process. |
| 131 // TODO(earthdok): Re-enable on CrOS http://crbug.com/360622 |
| 132 #if (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ |
| 133 defined(THREAD_SANITIZER)) && !defined(OS_CHROMEOS) |
| 134 // Some sanitizer tools rely on exit handlers (e.g. to run leak detection, |
| 135 // or dump code coverage data to disk). Instead of exiting the process |
| 136 // immediately, we give it 60 seconds to run exit handlers. |
| 137 CHECK(CreateWaitAndExitThread(base::TimeDelta::FromSeconds(60))); |
| 138 #if defined(LEAK_SANITIZER) |
| 139 // Invoke LeakSanitizer early to avoid detecting shutdown-only leaks. If |
| 140 // leaks are found, the process will exit here. |
| 141 __lsan_do_leak_check(); |
| 142 #endif |
| 143 #else |
92 _exit(0); | 144 _exit(0); |
| 145 #endif |
93 } | 146 } |
94 | 147 |
95 protected: | 148 protected: |
96 virtual ~SuicideOnChannelErrorFilter() {} | 149 virtual ~SuicideOnChannelErrorFilter() {} |
97 }; | 150 }; |
98 | 151 |
99 #endif // OS(POSIX) | 152 #endif // OS(POSIX) |
100 | 153 |
101 #if defined(OS_ANDROID) | 154 #if defined(OS_ANDROID) |
102 ChildThread* g_child_thread = NULL; | 155 ChildThread* g_child_thread = NULL; |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 // inflight that would addref it. | 533 // inflight that would addref it. |
481 Send(new ChildProcessHostMsg_ShutdownRequest); | 534 Send(new ChildProcessHostMsg_ShutdownRequest); |
482 } | 535 } |
483 | 536 |
484 void ChildThread::EnsureConnected() { | 537 void ChildThread::EnsureConnected() { |
485 VLOG(0) << "ChildThread::EnsureConnected()"; | 538 VLOG(0) << "ChildThread::EnsureConnected()"; |
486 base::KillProcess(base::GetCurrentProcessHandle(), 0, false); | 539 base::KillProcess(base::GetCurrentProcessHandle(), 0, false); |
487 } | 540 } |
488 | 541 |
489 } // namespace content | 542 } // namespace content |
OLD | NEW |