Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Unified Diff: content/common/file_path_watcher/file_path_watcher_inotify.cc

Issue 6697020: Fixed shutdown concurrency issues in FilePathWatcher. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Introduced CancelTask to simplify cleanup. Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/file_path_watcher/file_path_watcher_inotify.cc
diff --git a/content/common/file_path_watcher/file_path_watcher_inotify.cc b/content/common/file_path_watcher/file_path_watcher_inotify.cc
index ac9e5ce26d19ce77e4e171baf5b2ac6cad47412b..e4017e9933fb500eef8a4b111766760576690248 100644
--- a/content/common/file_path_watcher/file_path_watcher_inotify.cc
+++ b/content/common/file_path_watcher/file_path_watcher_inotify.cc
@@ -80,7 +80,8 @@ class InotifyReader {
DISALLOW_COPY_AND_ASSIGN(InotifyReader);
};
-class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {
+class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate,
+ public MessageLoop::DestructionObserver {
public:
FilePathWatcherImpl();
@@ -103,9 +104,17 @@ class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {
// Cancel the watch. This unregisters the instance with InotifyReader.
virtual void Cancel() OVERRIDE;
+ // Deletion of the FilePathWatcher will call Cancel() to dispose of this
+ // object in the right thread. This also observes destruction of the required
+ // cleanup thread, in case it quits before Cancel() is called.
+ virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
+
private:
virtual ~FilePathWatcherImpl() {}
+ // Cleans up and stops observing the |message_loop_| thread.
+ void CancelOnMessageLoopThread() OVERRIDE;
+
// Inotify watches are installed for all directory components of |target_|. A
// WatchEntry instance holds the watch descriptor for a component and the
// subdirectory for that identifies the next component.
@@ -363,6 +372,8 @@ bool FilePathWatcherImpl::Watch(const FilePath& path,
set_message_loop(base::MessageLoopProxy::CreateForCurrentThread());
delegate_ = delegate;
target_ = path;
+ MessageLoop::current()->AddDestructionObserver(this);
+
std::vector<FilePath::StringType> comps;
target_.GetComponents(&comps);
DCHECK(!comps.empty());
@@ -376,26 +387,39 @@ bool FilePathWatcherImpl::Watch(const FilePath& path,
}
void FilePathWatcherImpl::Cancel() {
- if (!message_loop().get()) {
- // Watch was never called, so exit.
+ if (!delegate_) {
+ // Watch was never called, or the |message_loop_| thread is already gone.
+ set_cancelled();
return;
}
// Switch to the message_loop_ if necessary so we can access |watches_|.
if (!message_loop()->BelongsToCurrentThread()) {
message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(this, &FilePathWatcherImpl::Cancel));
- return;
+ new FilePathWatcher::CancelTask(this));
+ } else {
+ CancelOnMessageLoopThread();
}
+}
- for (WatchVector::iterator watch_entry(watches_.begin());
- watch_entry != watches_.end(); ++watch_entry) {
- if (watch_entry->watch_ != InotifyReader::kInvalidWatch)
- g_inotify_reader.Get().RemoveWatch(watch_entry->watch_, this);
+void FilePathWatcherImpl::CancelOnMessageLoopThread() {
+ if (!is_cancelled()) {
+ set_cancelled();
+ MessageLoop::current()->RemoveDestructionObserver(this);
+
+ for (WatchVector::iterator watch_entry(watches_.begin());
+ watch_entry != watches_.end(); ++watch_entry) {
+ if (watch_entry->watch_ != InotifyReader::kInvalidWatch)
+ g_inotify_reader.Get().RemoveWatch(watch_entry->watch_, this);
+ }
+ watches_.clear();
+ delegate_ = NULL;
+ target_.clear();
}
- watches_.clear();
- delegate_ = NULL;
- target_.clear();
+}
+
+void FilePathWatcherImpl::WillDestroyCurrentMessageLoop() {
+ CancelOnMessageLoopThread();
}
bool FilePathWatcherImpl::UpdateWatches() {

Powered by Google App Engine
This is Rietveld 408576698