Commit 33fee2e5 authored by piman@chromium.org's avatar piman@chromium.org

Fix GpuChannelHost destruction races.

GpuChannelHost::MessageFilter can outlive GpuChannelHost, so make sure it
doesn't use a raw pointer to it.
Also ensure the BrowserGpuChannelHostFactory outlives the IO thread.

BUG=168282


Review URL: https://chromiumcodereview.appspot.com/11886005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176557 0039d316-1c4b-4281-b951-d872f2087c98
parent 8572c487
...@@ -214,9 +214,8 @@ class AcceleratedCompositingBlockedTest : public GpuFeatureTest { ...@@ -214,9 +214,8 @@ class AcceleratedCompositingBlockedTest : public GpuFeatureTest {
} }
}; };
#if (defined(OS_WIN) && defined(USE_AURA)) || defined(OS_CHROMEOS) #if (defined(OS_WIN) && defined(USE_AURA))
// Compositing is always on for Windows Aura. // Compositing is always on for Windows Aura.
// Disabled on chrome os due to http://crbug.com/167806
#define MAYBE_AcceleratedCompositingBlocked DISABLED_AcceleratedCompositingBlocked #define MAYBE_AcceleratedCompositingBlocked DISABLED_AcceleratedCompositingBlocked
#else #else
#define MAYBE_AcceleratedCompositingBlocked AcceleratedCompositingBlocked #define MAYBE_AcceleratedCompositingBlocked AcceleratedCompositingBlocked
...@@ -385,12 +384,7 @@ IN_PROC_BROWSER_TEST_F(WebGLMultisamplingTest, MultisamplingDisabled) { ...@@ -385,12 +384,7 @@ IN_PROC_BROWSER_TEST_F(WebGLMultisamplingTest, MultisamplingDisabled) {
RunTest(url, "\"FALSE\"", true); RunTest(url, "\"FALSE\"", true);
} }
#if defined(OS_LINUX) IN_PROC_BROWSER_TEST_F(GpuFeatureTest, Canvas2DAllowed) {
#define MAYBE_Canvas2DAllowed DISABLED_Canvas2DAllowed
#else
#define MAYBE_Canvas2DAllowed Canvas2DAllowed
#endif
IN_PROC_BROWSER_TEST_F(GpuFeatureTest, MAYBE_Canvas2DAllowed) {
// Accelerated canvas 2D is not supported on XP. // Accelerated canvas 2D is not supported on XP.
if (GPUTestBotConfig::CurrentConfigMatches("XP")) if (GPUTestBotConfig::CurrentConfigMatches("XP"))
return; return;
......
...@@ -522,7 +522,6 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() { ...@@ -522,7 +522,6 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
#if defined(USE_AURA) #if defined(USE_AURA)
ImageTransportFactory::Terminate(); ImageTransportFactory::Terminate();
#endif #endif
BrowserGpuChannelHostFactory::Terminate();
// The device monitors are using |system_monitor_| as dependency, so delete // The device monitors are using |system_monitor_| as dependency, so delete
// them before |system_monitor_| goes away. // them before |system_monitor_| goes away.
...@@ -627,6 +626,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() { ...@@ -627,6 +626,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
BrowserThreadImpl::ShutdownThreadPool(); BrowserThreadImpl::ShutdownThreadPool();
#if !defined(OS_IOS) #if !defined(OS_IOS)
// Must happen after the IO thread is shutdown since this may be accessed from
// it.
BrowserGpuChannelHostFactory::Terminate();
// Must happen after the I/O thread is shutdown since this class lives on the // Must happen after the I/O thread is shutdown since this class lives on the
// I/O thread and isn't threadsafe. // I/O thread and isn't threadsafe.
GamepadService::GetInstance()->Terminate(); GamepadService::GetInstance()->Terminate();
......
...@@ -52,7 +52,7 @@ void GpuChannelHost::Connect( ...@@ -52,7 +52,7 @@ void GpuChannelHost::Connect(
channel_->AddFilter(sync_filter_.get()); channel_->AddFilter(sync_filter_.get());
channel_filter_ = new MessageFilter(this); channel_filter_ = new MessageFilter(AsWeakPtr(), factory_);
// Install the filter last, because we intercept all leftover // Install the filter last, because we intercept all leftover
// messages. // messages.
...@@ -316,8 +316,11 @@ int32 GpuChannelHost::ReserveTransferBufferId() { ...@@ -316,8 +316,11 @@ int32 GpuChannelHost::ReserveTransferBufferId() {
GpuChannelHost::~GpuChannelHost() {} GpuChannelHost::~GpuChannelHost() {}
GpuChannelHost::MessageFilter::MessageFilter(GpuChannelHost* parent) GpuChannelHost::MessageFilter::MessageFilter(
: parent_(parent) { base::WeakPtr<GpuChannelHost> parent,
GpuChannelHostFactory* factory)
: parent_(parent),
factory_(factory) {
} }
GpuChannelHost::MessageFilter::~MessageFilter() {} GpuChannelHost::MessageFilter::~MessageFilter() {}
...@@ -326,7 +329,7 @@ void GpuChannelHost::MessageFilter::AddRoute( ...@@ -326,7 +329,7 @@ void GpuChannelHost::MessageFilter::AddRoute(
int route_id, int route_id,
base::WeakPtr<IPC::Listener> listener, base::WeakPtr<IPC::Listener> listener,
scoped_refptr<MessageLoopProxy> loop) { scoped_refptr<MessageLoopProxy> loop) {
DCHECK(parent_->factory_->IsIOThread()); DCHECK(factory_->IsIOThread());
DCHECK(listeners_.find(route_id) == listeners_.end()); DCHECK(listeners_.find(route_id) == listeners_.end());
GpuListenerInfo info; GpuListenerInfo info;
info.listener = listener; info.listener = listener;
...@@ -335,7 +338,7 @@ void GpuChannelHost::MessageFilter::AddRoute( ...@@ -335,7 +338,7 @@ void GpuChannelHost::MessageFilter::AddRoute(
} }
void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) { void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) {
DCHECK(parent_->factory_->IsIOThread()); DCHECK(factory_->IsIOThread());
ListenerMap::iterator it = listeners_.find(route_id); ListenerMap::iterator it = listeners_.find(route_id);
if (it != listeners_.end()) if (it != listeners_.end())
listeners_.erase(it); listeners_.erase(it);
...@@ -343,14 +346,14 @@ void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) { ...@@ -343,14 +346,14 @@ void GpuChannelHost::MessageFilter::RemoveRoute(int route_id) {
bool GpuChannelHost::MessageFilter::OnMessageReceived( bool GpuChannelHost::MessageFilter::OnMessageReceived(
const IPC::Message& message) { const IPC::Message& message) {
DCHECK(parent_->factory_->IsIOThread()); DCHECK(factory_->IsIOThread());
// Never handle sync message replies or we will deadlock here. // Never handle sync message replies or we will deadlock here.
if (message.is_reply()) if (message.is_reply())
return false; return false;
if (message.routing_id() == MSG_ROUTING_CONTROL) { if (message.routing_id() == MSG_ROUTING_CONTROL) {
MessageLoop* main_loop = parent_->factory_->GetMainLoop(); MessageLoop* main_loop = factory_->GetMainLoop();
main_loop->PostTask(FROM_HERE, main_loop->PostTask(FROM_HERE,
base::Bind(&GpuChannelHost::OnMessageReceived, base::Bind(&GpuChannelHost::OnMessageReceived,
parent_, parent_,
...@@ -374,12 +377,12 @@ bool GpuChannelHost::MessageFilter::OnMessageReceived( ...@@ -374,12 +377,12 @@ bool GpuChannelHost::MessageFilter::OnMessageReceived(
} }
void GpuChannelHost::MessageFilter::OnChannelError() { void GpuChannelHost::MessageFilter::OnChannelError() {
DCHECK(parent_->factory_->IsIOThread()); DCHECK(factory_->IsIOThread());
// Post the task to signal the GpuChannelHost before the proxies. That way, if // Post the task to signal the GpuChannelHost before the proxies. That way, if
// they themselves post a task to recreate the context, they will not try to // they themselves post a task to recreate the context, they will not try to
// re-use this channel host before it has a chance to mark itself lost. // re-use this channel host before it has a chance to mark itself lost.
MessageLoop* main_loop = parent_->factory_->GetMainLoop(); MessageLoop* main_loop = factory_->GetMainLoop();
main_loop->PostTask(FROM_HERE, main_loop->PostTask(FROM_HERE,
base::Bind(&GpuChannelHost::OnChannelError, parent_)); base::Bind(&GpuChannelHost::OnChannelError, parent_));
// Inform all the proxies that an error has occurred. This will be reported // Inform all the proxies that an error has occurred. This will be reported
......
...@@ -78,7 +78,8 @@ class CONTENT_EXPORT GpuChannelHostFactory { ...@@ -78,7 +78,8 @@ class CONTENT_EXPORT GpuChannelHostFactory {
// Encapsulates an IPC channel between the client and one GPU process. // Encapsulates an IPC channel between the client and one GPU process.
// On the GPU process side there's a corresponding GpuChannel. // On the GPU process side there's a corresponding GpuChannel.
class GpuChannelHost : public IPC::Sender, class GpuChannelHost : public IPC::Sender,
public base::RefCountedThreadSafe<GpuChannelHost> { public base::RefCountedThreadSafe<GpuChannelHost>,
public base::SupportsWeakPtr<GpuChannelHost> {
public: public:
enum State { enum State {
// Not yet connected. // Not yet connected.
...@@ -185,7 +186,8 @@ class GpuChannelHost : public IPC::Sender, ...@@ -185,7 +186,8 @@ class GpuChannelHost : public IPC::Sender,
// to the correct message loop. // to the correct message loop.
class MessageFilter : public IPC::ChannelProxy::MessageFilter { class MessageFilter : public IPC::ChannelProxy::MessageFilter {
public: public:
explicit MessageFilter(GpuChannelHost* parent); MessageFilter(base::WeakPtr<GpuChannelHost> parent,
GpuChannelHostFactory* factory);
void AddRoute(int route_id, void AddRoute(int route_id,
base::WeakPtr<IPC::Listener> listener, base::WeakPtr<IPC::Listener> listener,
...@@ -199,7 +201,12 @@ class GpuChannelHost : public IPC::Sender, ...@@ -199,7 +201,12 @@ class GpuChannelHost : public IPC::Sender,
private: private:
virtual ~MessageFilter(); virtual ~MessageFilter();
GpuChannelHost* parent_; // Note: this reference can only be used to post tasks back to the
// GpuChannelHost, it is illegal to dereference on the IO thread where the
// MessageFilter lives.
base::WeakPtr<GpuChannelHost> parent_;
GpuChannelHostFactory* factory_;
typedef base::hash_map<int, GpuListenerInfo> ListenerMap; typedef base::hash_map<int, GpuListenerInfo> ListenerMap;
ListenerMap listeners_; ListenerMap listeners_;
......
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