Commit 06aac852 authored by lfg's avatar lfg Committed by Commit bot

Drop queued IPC messages if the child process dies while spawning.

BUG=464633

Review URL: https://codereview.chromium.org/1018043004

Cr-Commit-Position: refs/heads/master@{#321878}
parent 8ebeef2e
...@@ -98,6 +98,12 @@ class ChildProcessLauncher::Context ...@@ -98,6 +98,12 @@ class ChildProcessLauncher::Context
void SetProcessBackgrounded(bool background); void SetProcessBackgrounded(bool background);
Client* ReplaceClientForTest(Client* client) {
Client* ret = client_;
client_ = client;
return ret;
}
private: private:
friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>; friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>;
...@@ -623,4 +629,9 @@ void ChildProcessLauncher::SetTerminateChildOnShutdown( ...@@ -623,4 +629,9 @@ void ChildProcessLauncher::SetTerminateChildOnShutdown(
context_->set_terminate_child_on_shutdown(terminate_on_shutdown); context_->set_terminate_child_on_shutdown(terminate_on_shutdown);
} }
ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
Client* client) {
return context_->ReplaceClientForTest(client);
}
} // namespace content } // namespace content
...@@ -76,6 +76,10 @@ class CONTENT_EXPORT ChildProcessLauncher { ...@@ -76,6 +76,10 @@ class CONTENT_EXPORT ChildProcessLauncher {
// shutdown. // shutdown.
void SetTerminateChildOnShutdown(bool terminate_on_shutdown); void SetTerminateChildOnShutdown(bool terminate_on_shutdown);
// Replaces the ChildProcessLauncher::Client for testing purposes. Returns the
// previous client.
Client* ReplaceClientForTest(Client* client);
private: private:
class Context; class Context;
......
...@@ -3,13 +3,41 @@ ...@@ -3,13 +3,41 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "base/command_line.h" #include "base/command_line.h"
#include "content/browser/child_process_launcher.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h" #include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
namespace {
class MockChildProcessLauncherClient
: public content::ChildProcessLauncher::Client {
public:
MockChildProcessLauncherClient()
: client_(nullptr), simulate_failure_(false) {}
void OnProcessLaunched() override {
if (simulate_failure_)
client_->OnProcessLaunchFailed();
else
client_->OnProcessLaunched();
};
void OnProcessLaunchFailed() override { client_->OnProcessLaunchFailed(); };
content::ChildProcessLauncher::Client* client_;
bool simulate_failure_;
};
}
namespace content { namespace content {
typedef ContentBrowserTest ChildProcessLauncherBrowserTest; class ChildProcessLauncherBrowserTest : public ContentBrowserTest {};
class StatsTableBrowserTest : public ChildProcessLauncherBrowserTest { class StatsTableBrowserTest : public ChildProcessLauncherBrowserTest {
public: public:
...@@ -22,4 +50,44 @@ IN_PROC_BROWSER_TEST_F(StatsTableBrowserTest, StartWithStatTable) { ...@@ -22,4 +50,44 @@ IN_PROC_BROWSER_TEST_F(StatsTableBrowserTest, StartWithStatTable) {
NavigateToURL(shell(), GURL("about:blank")); NavigateToURL(shell(), GURL("about:blank"));
} }
IN_PROC_BROWSER_TEST_F(ChildProcessLauncherBrowserTest, ChildSpawnFail) {
GURL url("about:blank");
Shell* window = shell();
MockChildProcessLauncherClient* client(nullptr);
// Navigate once and simulate a process failing to spawn.
TestNavigationObserver nav_observer1(window->web_contents(), 1);
client = new MockChildProcessLauncherClient;
window->LoadURL(url);
client->client_ = static_cast<RenderProcessHostImpl*>(
window->web_contents()->GetRenderProcessHost())
->child_process_launcher_->ReplaceClientForTest(client);
client->simulate_failure_ = true;
nav_observer1.Wait();
delete client;
NavigationEntry* last_entry =
shell()->web_contents()->GetController().GetLastCommittedEntry();
// Make sure we didn't navigate.
CHECK(!last_entry);
// Navigate again and let the process spawn correctly.
TestNavigationObserver nav_observer2(window->web_contents(), 1);
window->LoadURL(url);
nav_observer2.Wait();
last_entry = shell()->web_contents()->GetController().GetLastCommittedEntry();
// Make sure that we navigated to the proper URL.
CHECK(last_entry && last_entry->GetPageType() == PAGE_TYPE_NORMAL);
CHECK(shell()->web_contents()->GetLastCommittedURL() == url);
// Navigate again, using the same renderer.
url = GURL("data:text/html,dataurl");
TestNavigationObserver nav_observer3(window->web_contents(), 1);
window->LoadURL(url);
nav_observer3.Wait();
last_entry = shell()->web_contents()->GetController().GetLastCommittedEntry();
// Make sure that we navigated to the proper URL.
CHECK(last_entry && last_entry->GetPageType() == PAGE_TYPE_NORMAL);
CHECK(shell()->web_contents()->GetLastCommittedURL() == url);
}
} // namespace content } // namespace content
...@@ -2088,6 +2088,10 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead, ...@@ -2088,6 +2088,10 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
child_process_launcher_.reset(); child_process_launcher_.reset();
channel_.reset(); channel_.reset();
while (!queued_messages_.empty()) {
delete queued_messages_.front();
queued_messages_.pop();
}
within_process_died_observer_ = true; within_process_died_observer_ = true;
NotificationService::current()->Notify( NotificationService::current()->Notify(
......
...@@ -303,6 +303,7 @@ class CONTENT_EXPORT RenderProcessHostImpl ...@@ -303,6 +303,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
private: private:
friend class VisitRelayingRenderProcessHost; friend class VisitRelayingRenderProcessHost;
friend class ChildProcessLauncherBrowserTest_ChildSpawnFail_Test;
scoped_ptr<IPC::ChannelProxy> CreateChannelProxy( scoped_ptr<IPC::ChannelProxy> CreateChannelProxy(
const std::string& channel_id); const std::string& channel_id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment