Index: chrome/browser/process_singleton_linux.cc |
diff --git a/chrome/browser/process_singleton_linux.cc b/chrome/browser/process_singleton_linux.cc |
index 65d3567fafafe3ec117b5508466dfda26e844f6e..cbf6492fa22cd9caec07f2be5101d81734ab2d48 100644 |
--- a/chrome/browser/process_singleton_linux.cc |
+++ b/chrome/browser/process_singleton_linux.cc |
@@ -59,6 +59,7 @@ |
#include "base/base_paths.h" |
#include "base/basictypes.h" |
+#include "base/bind.h" |
#include "base/command_line.h" |
#include "base/eintr_wrapper.h" |
#include "base/file_path.h" |
@@ -461,7 +462,8 @@ bool ConnectSocket(ScopedSocket* socket, |
class ProcessSingleton::LinuxWatcher |
: public MessageLoopForIO::Watcher, |
public MessageLoop::DestructionObserver, |
- public base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher> { |
+ public base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher, |
+ BrowserThread::DeleteOnIOThread> { |
public: |
// A helper class to read message from an established socket. |
class SocketReader : public MessageLoopForIO::Watcher { |
@@ -473,11 +475,13 @@ class ProcessSingleton::LinuxWatcher |
ui_message_loop_(ui_message_loop), |
fd_(fd), |
bytes_read_(0) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
// Wait for reads. |
MessageLoopForIO::current()->WatchFileDescriptor( |
fd, true, MessageLoopForIO::WATCH_READ, &fd_reader_, this); |
+ // If we haven't completed in a reasonable amount of time, give up. |
timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeoutInSeconds), |
- this, &SocketReader::OnTimerExpiry); |
+ this, &SocketReader::CleanupAndDeleteSelf); |
} |
virtual ~SocketReader() { |
@@ -496,8 +500,9 @@ class ProcessSingleton::LinuxWatcher |
void FinishWithACK(const char *message, size_t length); |
private: |
- // If we haven't completed in a reasonable amount of time, give up. |
- void OnTimerExpiry() { |
+ void CleanupAndDeleteSelf() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
parent_->RemoveSocketReader(this); |
// We're deleted beyond this point. |
} |
@@ -540,7 +545,7 @@ class ProcessSingleton::LinuxWatcher |
// |reader| is for sending back ACK message. |
void HandleMessage(const std::string& current_dir, |
const std::vector<std::string>& argv, |
- SocketReader *reader); |
+ SocketReader* reader); |
// MessageLoopForIO::Watcher impl. These run on the IO thread. |
virtual void OnFileCanReadWithoutBlocking(int fd); |
@@ -555,9 +560,11 @@ class ProcessSingleton::LinuxWatcher |
} |
private: |
- friend class base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher>; |
+ friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>; |
+ friend class DeleteTask<ProcessSingleton::LinuxWatcher>; |
virtual ~LinuxWatcher() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
STLDeleteElements(&readers_); |
} |
@@ -579,6 +586,7 @@ class ProcessSingleton::LinuxWatcher |
}; |
void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
// Accepting incoming client. |
sockaddr_un from; |
socklen_t from_len = sizeof(from); |
@@ -664,6 +672,7 @@ void ProcessSingleton::LinuxWatcher::HandleMessage( |
} |
void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
DCHECK(reader); |
readers_.erase(reader); |
delete reader; |
@@ -675,6 +684,7 @@ void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) { |
void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking( |
int fd) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
DCHECK_EQ(fd, fd_); |
while (bytes_read_ < sizeof(buf_)) { |
ssize_t rv = HANDLE_EINTR( |
@@ -702,6 +712,7 @@ void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking( |
if (bytes_read_ < kMinMessageLength) { |
buf_[bytes_read_] = 0; |
LOG(ERROR) << "Invalid socket message (wrong length):" << buf_; |
+ CleanupAndDeleteSelf(); |
return; |
} |
@@ -711,6 +722,7 @@ void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking( |
if (tokens.size() < 3 || tokens[0] != kStartToken) { |
LOG(ERROR) << "Wrong message format: " << str; |
+ CleanupAndDeleteSelf(); |
return; |
} |
@@ -725,9 +737,9 @@ void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking( |
tokens.erase(tokens.begin()); |
// Return to the UI thread to handle opening a new browser tab. |
- ui_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
- parent_, |
+ ui_message_loop_->PostTask(FROM_HERE, base::Bind( |
&ProcessSingleton::LinuxWatcher::HandleMessage, |
+ parent_, |
current_dir, |
tokens, |
this)); |
@@ -747,8 +759,13 @@ void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK( |
if (shutdown(fd_, SHUT_WR) < 0) |
PLOG(ERROR) << "shutdown() failed"; |
- parent_->RemoveSocketReader(this); |
- // We are deleted beyond this point. |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, |
+ FROM_HERE, |
+ base::Bind(&ProcessSingleton::LinuxWatcher::RemoveSocketReader, |
+ parent_, |
+ this)); |
+ // We will be deleted once the posted RemoveSocketReader task runs. |
} |
/////////////////////////////////////////////////////////////////////////////// |
@@ -983,9 +1000,9 @@ bool ProcessSingleton::Create() { |
// socket. |
MessageLoop* ml = g_browser_process->io_thread()->message_loop(); |
DCHECK(ml); |
- ml->PostTask(FROM_HERE, NewRunnableMethod( |
- watcher_.get(), |
+ ml->PostTask(FROM_HERE, base::Bind( |
&ProcessSingleton::LinuxWatcher::StartListening, |
+ watcher_.get(), |
sock)); |
return true; |