Commit c3dd3384 authored by piman@chromium.org's avatar piman@chromium.org

Fix leak in GpuChannel

There may be remaining messages in the deferred queue on unclean teardown.
Delete those.

Also, a little bit of cleanup in the area:
- GpuChannel doesn't need to be refcounted
- It's ok to copy WeakPtr across threads, as long as they're only dereferenced
on the thread that the factory is destroyed. So no need for the extra
indirection.

BUG=374843

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272584 0039d316-1c4b-4281-b951-d872f2087c98
parent 1d7be68b
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "base/debug/trace_event.h" #include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h" #include "base/message_loop/message_loop_proxy.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "content/common/gpu/devtools_gpu_agent.h" #include "content/common/gpu/devtools_gpu_agent.h"
...@@ -71,8 +72,7 @@ const int64 kStopPreemptThresholdMs = kVsyncIntervalMs; ...@@ -71,8 +72,7 @@ const int64 kStopPreemptThresholdMs = kVsyncIntervalMs;
// - it generates mailbox names for clients of the GPU process on the IO thread. // - it generates mailbox names for clients of the GPU process on the IO thread.
class GpuChannelMessageFilter : public IPC::MessageFilter { class GpuChannelMessageFilter : public IPC::MessageFilter {
public: public:
// Takes ownership of gpu_channel (see below). GpuChannelMessageFilter(base::WeakPtr<GpuChannel> gpu_channel,
GpuChannelMessageFilter(base::WeakPtr<GpuChannel>* gpu_channel,
scoped_refptr<SyncPointManager> sync_point_manager, scoped_refptr<SyncPointManager> sync_point_manager,
scoped_refptr<base::MessageLoopProxy> message_loop) scoped_refptr<base::MessageLoopProxy> message_loop)
: preemption_state_(IDLE), : preemption_state_(IDLE),
...@@ -81,8 +81,7 @@ class GpuChannelMessageFilter : public IPC::MessageFilter { ...@@ -81,8 +81,7 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
sync_point_manager_(sync_point_manager), sync_point_manager_(sync_point_manager),
message_loop_(message_loop), message_loop_(message_loop),
messages_forwarded_to_channel_(0), messages_forwarded_to_channel_(0),
a_stub_is_descheduled_(false) { a_stub_is_descheduled_(false) {}
}
virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE { virtual void OnFilterAdded(IPC::Channel* channel) OVERRIDE {
DCHECK(!channel_); DCHECK(!channel_);
...@@ -153,10 +152,7 @@ class GpuChannelMessageFilter : public IPC::MessageFilter { ...@@ -153,10 +152,7 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
} }
protected: protected:
virtual ~GpuChannelMessageFilter() { virtual ~GpuChannelMessageFilter() {}
message_loop_->PostTask(FROM_HERE, base::Bind(
&GpuChannelMessageFilter::DeleteWeakPtrOnMainThread, gpu_channel_));
}
private: private:
enum PreemptionState { enum PreemptionState {
...@@ -337,7 +333,7 @@ class GpuChannelMessageFilter : public IPC::MessageFilter { ...@@ -337,7 +333,7 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
} }
static void InsertSyncPointOnMainThread( static void InsertSyncPointOnMainThread(
base::WeakPtr<GpuChannel>* gpu_channel, base::WeakPtr<GpuChannel> gpu_channel,
scoped_refptr<SyncPointManager> manager, scoped_refptr<SyncPointManager> manager,
int32 routing_id, int32 routing_id,
uint32 sync_point) { uint32 sync_point) {
...@@ -346,30 +342,23 @@ class GpuChannelMessageFilter : public IPC::MessageFilter { ...@@ -346,30 +342,23 @@ class GpuChannelMessageFilter : public IPC::MessageFilter {
// with it, but if that fails for any reason (channel or stub already // with it, but if that fails for any reason (channel or stub already
// deleted, invalid routing id), we need to retire the sync point // deleted, invalid routing id), we need to retire the sync point
// immediately. // immediately.
if (gpu_channel->get()) { if (gpu_channel) {
GpuCommandBufferStub* stub = gpu_channel->get()->LookupCommandBuffer( GpuCommandBufferStub* stub = gpu_channel->LookupCommandBuffer(routing_id);
routing_id);
if (stub) { if (stub) {
stub->AddSyncPoint(sync_point); stub->AddSyncPoint(sync_point);
GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point); GpuCommandBufferMsg_RetireSyncPoint message(routing_id, sync_point);
gpu_channel->get()->OnMessageReceived(message); gpu_channel->OnMessageReceived(message);
return; return;
} else { } else {
gpu_channel->get()->MessageProcessed(); gpu_channel->MessageProcessed();
} }
} }
manager->RetireSyncPoint(sync_point); manager->RetireSyncPoint(sync_point);
} }
static void DeleteWeakPtrOnMainThread( // NOTE: this weak pointer is never dereferenced on the IO thread, it's only
base::WeakPtr<GpuChannel>* gpu_channel) { // passed through - therefore the WeakPtr assumptions are respected.
delete gpu_channel; base::WeakPtr<GpuChannel> gpu_channel_;
}
// NOTE: this is a pointer to a weak pointer. It is never dereferenced on the
// IO thread, it's only passed through - therefore the WeakPtr assumptions are
// respected.
base::WeakPtr<GpuChannel>* gpu_channel_;
IPC::Channel* channel_; IPC::Channel* channel_;
scoped_refptr<SyncPointManager> sync_point_manager_; scoped_refptr<SyncPointManager> sync_point_manager_;
scoped_refptr<base::MessageLoopProxy> message_loop_; scoped_refptr<base::MessageLoopProxy> message_loop_;
...@@ -411,6 +400,11 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager, ...@@ -411,6 +400,11 @@ GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
} }
GpuChannel::~GpuChannel() {
STLDeleteElements(&deferred_messages_);
if (preempting_flag_.get())
preempting_flag_->Reset();
}
void GpuChannel::Init(base::MessageLoopProxy* io_message_loop, void GpuChannel::Init(base::MessageLoopProxy* io_message_loop,
base::WaitableEvent* shutdown_event) { base::WaitableEvent* shutdown_event) {
...@@ -425,13 +419,10 @@ void GpuChannel::Init(base::MessageLoopProxy* io_message_loop, ...@@ -425,13 +419,10 @@ void GpuChannel::Init(base::MessageLoopProxy* io_message_loop,
false, false,
shutdown_event)); shutdown_event));
base::WeakPtr<GpuChannel>* weak_ptr(new base::WeakPtr<GpuChannel>( filter_ =
weak_factory_.GetWeakPtr())); new GpuChannelMessageFilter(weak_factory_.GetWeakPtr(),
gpu_channel_manager_->sync_point_manager(),
filter_ = new GpuChannelMessageFilter( base::MessageLoopProxy::current());
weak_ptr,
gpu_channel_manager_->sync_point_manager(),
base::MessageLoopProxy::current());
io_message_loop_ = io_message_loop; io_message_loop_ = io_message_loop;
channel_->AddFilter(filter_.get()); channel_->AddFilter(filter_.get());
...@@ -632,11 +623,6 @@ void GpuChannel::MarkAllContextsLost() { ...@@ -632,11 +623,6 @@ void GpuChannel::MarkAllContextsLost() {
} }
} }
void GpuChannel::DestroySoon() {
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&GpuChannel::OnDestroy, this));
}
bool GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) { bool GpuChannel::AddRoute(int32 route_id, IPC::Listener* listener) {
return router_.AddRoute(route_id, listener); return router_.AddRoute(route_id, listener);
} }
...@@ -666,11 +652,6 @@ void GpuChannel::SetPreemptByFlag( ...@@ -666,11 +652,6 @@ void GpuChannel::SetPreemptByFlag(
} }
} }
GpuChannel::~GpuChannel() {
if (preempting_flag_.get())
preempting_flag_->Reset();
}
void GpuChannel::OnDestroy() { void GpuChannel::OnDestroy() {
TRACE_EVENT0("gpu", "GpuChannel::OnDestroy"); TRACE_EVENT0("gpu", "GpuChannel::OnDestroy");
gpu_channel_manager_->RemoveChannel(client_id_); gpu_channel_manager_->RemoveChannel(client_id_);
......
...@@ -50,9 +50,7 @@ class GpuWatchdog; ...@@ -50,9 +50,7 @@ class GpuWatchdog;
// Encapsulates an IPC channel between the GPU process and one renderer // Encapsulates an IPC channel between the GPU process and one renderer
// process. On the renderer side there's a corresponding GpuChannelHost. // process. On the renderer side there's a corresponding GpuChannelHost.
class GpuChannel : public IPC::Listener, class GpuChannel : public IPC::Listener, public IPC::Sender {
public IPC::Sender,
public base::RefCountedThreadSafe<GpuChannel> {
public: public:
// Takes ownership of the renderer process handle. // Takes ownership of the renderer process handle.
GpuChannel(GpuChannelManager* gpu_channel_manager, GpuChannel(GpuChannelManager* gpu_channel_manager,
...@@ -61,6 +59,7 @@ class GpuChannel : public IPC::Listener, ...@@ -61,6 +59,7 @@ class GpuChannel : public IPC::Listener,
gpu::gles2::MailboxManager* mailbox_manager, gpu::gles2::MailboxManager* mailbox_manager,
int client_id, int client_id,
bool software); bool software);
virtual ~GpuChannel();
void Init(base::MessageLoopProxy* io_message_loop, void Init(base::MessageLoopProxy* io_message_loop,
base::WaitableEvent* shutdown_event); base::WaitableEvent* shutdown_event);
...@@ -127,9 +126,6 @@ class GpuChannel : public IPC::Listener, ...@@ -127,9 +126,6 @@ class GpuChannel : public IPC::Listener,
void LoseAllContexts(); void LoseAllContexts();
void MarkAllContextsLost(); void MarkAllContextsLost();
// Destroy channel and all contained contexts.
void DestroySoon();
// Called to add a listener for a particular message routing ID. // Called to add a listener for a particular message routing ID.
// Returns true if succeeded. // Returns true if succeeded.
bool AddRoute(int32 route_id, IPC::Listener* listener); bool AddRoute(int32 route_id, IPC::Listener* listener);
...@@ -154,11 +150,7 @@ class GpuChannel : public IPC::Listener, ...@@ -154,11 +150,7 @@ class GpuChannel : public IPC::Listener,
uint64 GetMemoryUsage(); uint64 GetMemoryUsage();
protected:
virtual ~GpuChannel();
private: private:
friend class base::RefCountedThreadSafe<GpuChannel>;
friend class GpuChannelMessageFilter; friend class GpuChannelMessageFilter;
void OnDestroy(); void OnDestroy();
......
...@@ -98,7 +98,7 @@ GpuChannel* GpuChannelManager::LookupChannel(int32 client_id) { ...@@ -98,7 +98,7 @@ GpuChannel* GpuChannelManager::LookupChannel(int32 client_id) {
if (iter == gpu_channels_.end()) if (iter == gpu_channels_.end())
return NULL; return NULL;
else else
return iter->second.get(); return iter->second;
} }
bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) { bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) {
...@@ -133,14 +133,9 @@ void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) { ...@@ -133,14 +133,9 @@ void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) {
mailbox_manager = mailbox_manager_.get(); mailbox_manager = mailbox_manager_.get();
} }
scoped_refptr<GpuChannel> channel = new GpuChannel(this, scoped_ptr<GpuChannel> channel(new GpuChannel(
watchdog_, this, watchdog_, share_group, mailbox_manager, client_id, false));
share_group,
mailbox_manager,
client_id,
false);
channel->Init(io_message_loop_.get(), shutdown_event_); channel->Init(io_message_loop_.get(), shutdown_event_);
gpu_channels_[client_id] = channel;
channel_handle.name = channel->GetChannelName(); channel_handle.name = channel->GetChannelName();
#if defined(OS_POSIX) #if defined(OS_POSIX)
...@@ -151,6 +146,8 @@ void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) { ...@@ -151,6 +146,8 @@ void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) {
channel_handle.socket = base::FileDescriptor(renderer_fd, true); channel_handle.socket = base::FileDescriptor(renderer_fd, true);
#endif #endif
gpu_channels_.set(client_id, channel.Pass());
Send(new GpuHostMsg_ChannelEstablished(channel_handle)); Send(new GpuHostMsg_ChannelEstablished(channel_handle));
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/containers/hash_tables.h" #include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
...@@ -105,7 +105,7 @@ class GpuChannelManager : public IPC::Listener, ...@@ -105,7 +105,7 @@ class GpuChannelManager : public IPC::Listener,
int32 sync_point; int32 sync_point;
base::Closure callback; base::Closure callback;
}; };
typedef base::hash_map<int, scoped_refptr<GpuChannel> > GpuChannelMap; typedef base::ScopedPtrHashMap<int, GpuChannel> GpuChannelMap;
typedef std::deque<ImageOperation*> ImageOperationQueue; typedef std::deque<ImageOperation*> ImageOperationQueue;
// Message handlers. // Message handlers.
......
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