Index: content/common/child_thread.cc |
=================================================================== |
--- content/common/child_thread.cc (revision 148974) |
+++ content/common/child_thread.cc (working copy) |
@@ -32,6 +32,47 @@ |
using content::ResourceDispatcher; |
using tracked_objects::ThreadData; |
+namespace { |
+ |
+#if defined(OS_POSIX) |
+ |
+class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter { |
+ public: |
+ // IPC::ChannelProxy::MessageFilter |
+ virtual void OnChannelError() OVERRIDE { |
+ // For renderer/worker processes: |
+ // On POSIX, at least, one can install an unload handler which loops |
+ // forever and leave behind a renderer process which eats 100% CPU forever. |
+ // |
+ // This is because the terminate signals (ViewMsg_ShouldClose and the error |
+ // from the IPC channel) are routed to the main message loop but never |
+ // processed (because that message loop is stuck in V8). |
+ // |
+ // One could make the browser SIGKILL the renderers, but that leaves open a |
+ // large window where a browser failure (or a user, manually terminating |
+ // the browser because "it's stuck") will leave behind a process eating all |
+ // the CPU. |
+ // |
+ // So, we install a filter on the channel so that we can process this event |
+ // here and kill the process. |
+ // |
+ // We want to kill this process after giving it 30 seconds to run the exit |
+ // handlers. SIGALRM has a default disposition of terminating the |
+ // application. |
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kChildCleanExit)) |
+ alarm(30); |
+ else |
+ _exit(0); |
+ } |
+ |
+ protected: |
+ virtual ~SuicideOnChannelErrorFilter() {} |
+}; |
+ |
+#endif // OS(POSIX) |
+ |
+} // namespace |
+ |
ChildThread::ChildThread() { |
channel_name_ = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
switches::kProcessChannelID); |
@@ -66,6 +107,13 @@ |
channel_->AddFilter(histogram_message_filter_.get()); |
channel_->AddFilter(sync_message_filter_.get()); |
channel_->AddFilter(new ChildTraceMessageFilter()); |
+ |
+#if defined(OS_POSIX) |
+ // Check that --process-type is specified so we don't do this in unit tests |
+ // and single-process mode. |
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType)) |
+ channel_->AddFilter(new SuicideOnChannelErrorFilter()); |
+#endif |
} |
ChildThread::~ChildThread() { |