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/common/child_thread.h" | 5 #include "content/common/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/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/process.h" | 10 #include "base/process.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "ipc/ipc_sync_message_filter.h" | 25 #include "ipc/ipc_sync_message_filter.h" |
26 #include "webkit/glue/webkit_glue.h" | 26 #include "webkit/glue/webkit_glue.h" |
27 | 27 |
28 #if defined(OS_WIN) | 28 #if defined(OS_WIN) |
29 #include "content/common/handle_enumerator_win.h" | 29 #include "content/common/handle_enumerator_win.h" |
30 #endif | 30 #endif |
31 | 31 |
32 using content::ResourceDispatcher; | 32 using content::ResourceDispatcher; |
33 using tracked_objects::ThreadData; | 33 using tracked_objects::ThreadData; |
34 | 34 |
| 35 namespace { |
| 36 |
| 37 #if defined(OS_POSIX) |
| 38 |
| 39 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { |
| 40 public: |
| 41 // IPC::ChannelProxy::MessageFilter |
| 42 virtual void OnChannelError() OVERRIDE { |
| 43 // For renderer/worker processes: |
| 44 // On POSIX, at least, one can install an unload handler which loops |
| 45 // forever and leave behind a renderer process which eats 100% CPU forever. |
| 46 // |
| 47 // This is because the terminate signals (ViewMsg_ShouldClose and the error |
| 48 // from the IPC channel) are routed to the main message loop but never |
| 49 // processed (because that message loop is stuck in V8). |
| 50 // |
| 51 // One could make the browser SIGKILL the renderers, but that leaves open a |
| 52 // large window where a browser failure (or a user, manually terminating |
| 53 // the browser because "it's stuck") will leave behind a process eating all |
| 54 // the CPU. |
| 55 // |
| 56 // So, we install a filter on the channel so that we can process this event |
| 57 // here and kill the process. |
| 58 // |
| 59 // We want to kill this process after giving it 30 seconds to run the exit |
| 60 // handlers. SIGALRM has a default disposition of terminating the |
| 61 // application. |
| 62 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kChildCleanExit)) |
| 63 alarm(30); |
| 64 else |
| 65 _exit(0); |
| 66 } |
| 67 |
| 68 protected: |
| 69 virtual ~SuicideOnChannelErrorFilter() {} |
| 70 }; |
| 71 |
| 72 #endif // OS(POSIX) |
| 73 |
| 74 } // namespace |
| 75 |
35 ChildThread::ChildThread() { | 76 ChildThread::ChildThread() { |
36 channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 77 channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
37 switches::kProcessChannelID); | 78 switches::kProcessChannelID); |
38 Init(); | 79 Init(); |
39 } | 80 } |
40 | 81 |
41 ChildThread::ChildThread(const std::string& channel_name) | 82 ChildThread::ChildThread(const std::string& channel_name) |
42 : channel_name_(channel_name) { | 83 : channel_name_(channel_name) { |
43 Init(); | 84 Init(); |
44 } | 85 } |
(...skipping 14 matching lines...) Expand all Loading... |
59 file_system_dispatcher_.reset(new FileSystemDispatcher()); | 100 file_system_dispatcher_.reset(new FileSystemDispatcher()); |
60 quota_dispatcher_.reset(new QuotaDispatcher()); | 101 quota_dispatcher_.reset(new QuotaDispatcher()); |
61 | 102 |
62 sync_message_filter_ = | 103 sync_message_filter_ = |
63 new IPC::SyncMessageFilter(ChildProcess::current()->GetShutDownEvent()); | 104 new IPC::SyncMessageFilter(ChildProcess::current()->GetShutDownEvent()); |
64 histogram_message_filter_ = new content::ChildHistogramMessageFilter(); | 105 histogram_message_filter_ = new content::ChildHistogramMessageFilter(); |
65 | 106 |
66 channel_->AddFilter(histogram_message_filter_.get()); | 107 channel_->AddFilter(histogram_message_filter_.get()); |
67 channel_->AddFilter(sync_message_filter_.get()); | 108 channel_->AddFilter(sync_message_filter_.get()); |
68 channel_->AddFilter(new ChildTraceMessageFilter()); | 109 channel_->AddFilter(new ChildTraceMessageFilter()); |
| 110 |
| 111 #if defined(OS_POSIX) |
| 112 // Check that --process-type is specified so we don't do this in unit tests |
| 113 // and single-process mode. |
| 114 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType)) |
| 115 channel_->AddFilter(new SuicideOnChannelErrorFilter()); |
| 116 #endif |
69 } | 117 } |
70 | 118 |
71 ChildThread::~ChildThread() { | 119 ChildThread::~ChildThread() { |
72 #ifdef IPC_MESSAGE_LOG_ENABLED | 120 #ifdef IPC_MESSAGE_LOG_ENABLED |
73 IPC::Logging::GetInstance()->SetIPCSender(NULL); | 121 IPC::Logging::GetInstance()->SetIPCSender(NULL); |
74 #endif | 122 #endif |
75 | 123 |
76 channel_->RemoveFilter(histogram_message_filter_.get()); | 124 channel_->RemoveFilter(histogram_message_filter_.get()); |
77 channel_->RemoveFilter(sync_message_filter_.get()); | 125 channel_->RemoveFilter(sync_message_filter_.get()); |
78 | 126 |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 } | 325 } |
278 | 326 |
279 // The child process shutdown sequence is a request response based mechanism, | 327 // The child process shutdown sequence is a request response based mechanism, |
280 // where we send out an initial feeler request to the child process host | 328 // where we send out an initial feeler request to the child process host |
281 // instance in the browser to verify if it's ok to shutdown the child process. | 329 // instance in the browser to verify if it's ok to shutdown the child process. |
282 // The browser then sends back a response if it's ok to shutdown. This avoids | 330 // The browser then sends back a response if it's ok to shutdown. This avoids |
283 // race conditions if the process refcount is 0 but there's an IPC message | 331 // race conditions if the process refcount is 0 but there's an IPC message |
284 // inflight that would addref it. | 332 // inflight that would addref it. |
285 Send(new ChildProcessHostMsg_ShutdownRequest); | 333 Send(new ChildProcessHostMsg_ShutdownRequest); |
286 } | 334 } |
OLD | NEW |