Commit f0ef2da9 authored by piman@google.com's avatar piman@google.com

linux: fix renderer/plugin crash when loading multiple pages with plugins

Currently we crash if one renderer has a plugin and another one has a plugin that gets destroyed, and started again (e.g. reload). We get away with reload on a single page currently because the process gets torn down.
This properly cleans up the socket and channel mapping on both sides, so it can be restarted.

Review URL: http://codereview.chromium.org/155174


git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20112 0039d316-1c4b-4281-b951-d872f2087c98
parent 3bc33c64
...@@ -89,12 +89,14 @@ class PipeMap { ...@@ -89,12 +89,14 @@ class PipeMap {
// Remove the mapping for the given channel id. No error is signaled if the // Remove the mapping for the given channel id. No error is signaled if the
// channel_id doesn't exist // channel_id doesn't exist
void Remove(const std::string& channel_id) { void RemoveAndClose(const std::string& channel_id) {
AutoLock locked(lock_); AutoLock locked(lock_);
ChannelToFDMap::iterator i = map_.find(channel_id); ChannelToFDMap::iterator i = map_.find(channel_id);
if (i != map_.end()) if (i != map_.end()) {
HANDLE_EINTR(close(i->second));
map_.erase(i); map_.erase(i);
}
} }
// Insert a mapping from @channel_id to @fd. It's a fatal error to insert a // Insert a mapping from @channel_id to @fd. It's a fatal error to insert a
...@@ -270,6 +272,11 @@ void AddChannelSocket(const std::string& name, int socket) { ...@@ -270,6 +272,11 @@ void AddChannelSocket(const std::string& name, int socket) {
Singleton<PipeMap>()->Insert(name, socket); Singleton<PipeMap>()->Insert(name, socket);
} }
// static
void RemoveAndCloseChannelSocket(const std::string& name) {
Singleton<PipeMap>()->RemoveAndClose(name);
}
// static // static
bool SocketPair(int* fd1, int* fd2) { bool SocketPair(int* fd1, int* fd2) {
int pipe_fds[2]; int pipe_fds[2];
...@@ -423,8 +430,7 @@ bool Channel::ChannelImpl::ProcessIncomingMessages() { ...@@ -423,8 +430,7 @@ bool Channel::ChannelImpl::ProcessIncomingMessages() {
DCHECK(bytes_read); DCHECK(bytes_read);
if (client_pipe_ != -1) { if (client_pipe_ != -1) {
Singleton<PipeMap>()->Remove(pipe_name_); Singleton<PipeMap>()->RemoveAndClose(pipe_name_);
HANDLE_EINTR(close(client_pipe_));
client_pipe_ = -1; client_pipe_ = -1;
} }
...@@ -776,8 +782,7 @@ void Channel::ChannelImpl::Close() { ...@@ -776,8 +782,7 @@ void Channel::ChannelImpl::Close() {
pipe_ = -1; pipe_ = -1;
} }
if (client_pipe_ != -1) { if (client_pipe_ != -1) {
Singleton<PipeMap>()->Remove(pipe_name_); Singleton<PipeMap>()->RemoveAndClose(pipe_name_);
HANDLE_EINTR(close(client_pipe_));
client_pipe_ = -1; client_pipe_ = -1;
} }
......
...@@ -23,6 +23,9 @@ namespace IPC { ...@@ -23,6 +23,9 @@ namespace IPC {
// our behalf and they've just shipped us the socket. // our behalf and they've just shipped us the socket.
void AddChannelSocket(const std::string& name, int socket); void AddChannelSocket(const std::string& name, int socket);
// Remove the channel name mapping, and close the corresponding socket.
void RemoveAndCloseChannelSocket(const std::string& name);
// Construct a socket pair appropriate for IPC: UNIX domain, nonblocking. // Construct a socket pair appropriate for IPC: UNIX domain, nonblocking.
// Returns false on error. // Returns false on error.
bool SocketPair(int* fd1, int* fd2); bool SocketPair(int* fd1, int* fd2);
......
...@@ -48,7 +48,8 @@ PluginChannel::~PluginChannel() { ...@@ -48,7 +48,8 @@ PluginChannel::~PluginChannel() {
if (renderer_handle_) if (renderer_handle_)
base::CloseProcessHandle(renderer_handle_); base::CloseProcessHandle(renderer_handle_);
#if defined(OS_POSIX) #if defined(OS_POSIX)
// If we still have the FD, close it. IPC::RemoveAndCloseChannelSocket(channel_name());
// If we still have the renderer FD, close it.
if (renderer_fd_ != -1) { if (renderer_fd_ != -1) {
close(renderer_fd_); close(renderer_fd_);
} }
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
#include "chrome/common/plugin_messages.h" #include "chrome/common/plugin_messages.h"
#if defined(OS_POSIX)
#include "chrome/common/ipc_channel_posix.h"
#endif
// A simple MessageFilter that will ignore all messages and respond to sync // A simple MessageFilter that will ignore all messages and respond to sync
// messages with an error when is_listening_ is false. // messages with an error when is_listening_ is false.
class IsListeningFilter : public IPC::ChannelProxy::MessageFilter { class IsListeningFilter : public IPC::ChannelProxy::MessageFilter {
...@@ -76,6 +80,9 @@ PluginChannelHost::PluginChannelHost() { ...@@ -76,6 +80,9 @@ PluginChannelHost::PluginChannelHost() {
} }
PluginChannelHost::~PluginChannelHost() { PluginChannelHost::~PluginChannelHost() {
#if defined(OS_POSIX)
IPC::RemoveAndCloseChannelSocket(channel_name());
#endif
} }
bool PluginChannelHost::Init(MessageLoop* ipc_message_loop, bool PluginChannelHost::Init(MessageLoop* ipc_message_loop,
......
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