summaryrefslogtreecommitdiff
path: root/base/files/file_path_watcher_kqueue.cc
diff options
context:
space:
mode:
authorHidehiko Abe <hidehiko@google.com>2017-12-13 18:59:30 +0900
committerHidehiko Abe <hidehiko@google.com>2017-12-13 23:41:17 +0900
commit36040ed30c39d2106a2cd5ec033e98b71302a744 (patch)
treedc486be512fe418b1cd79a66c11556174de03c4f /base/files/file_path_watcher_kqueue.cc
parent1216c7fc80727dea7cb9c5f946688f4b98ccd23c (diff)
downloadlibchrome-36040ed30c39d2106a2cd5ec033e98b71302a744.tar.gz
libchrome: Uprev the library to r456626 from Chromium
Pulled the latest and greatest version of libchrome from Chromium. The merge was done against r456626 which corresponds to git commit 08266b3fca707804065a2cfd60331722ade41969 of Mar 14, 2017 Notable changes are: - FOR_EACH_OBSERVER macro removed (replaced by use of C++ 11 range-base for loop) - base::Values no more FundamentalValue - stl_util moved to base namespace - some scoped pointers removed in crypto/ in favor of BoringSSL UniquePtr. - path() accessor renamed to GetPath() in ScopedTempDir (and other classes) - introduction of base::CallbackOnce Test: All unit-tests should still pass. Change-Id: I1e65efb167fa708e35ed7c6492f1cb66a6a46104 Merged-In: I180f9defc7607f462389fae17701fff553c4a2d0
Diffstat (limited to 'base/files/file_path_watcher_kqueue.cc')
-rw-r--r--base/files/file_path_watcher_kqueue.cc163
1 files changed, 72 insertions, 91 deletions
diff --git a/base/files/file_path_watcher_kqueue.cc b/base/files/file_path_watcher_kqueue.cc
index 6d034cd9a2..a28726acb0 100644
--- a/base/files/file_path_watcher_kqueue.cc
+++ b/base/files/file_path_watcher_kqueue.cc
@@ -12,7 +12,7 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/threading/sequenced_task_runner_handle.h"
// On some platforms these are not defined.
#if !defined(EV_RECEIPT)
@@ -26,7 +26,9 @@ namespace base {
FilePathWatcherKQueue::FilePathWatcherKQueue() : kqueue_(-1) {}
-FilePathWatcherKQueue::~FilePathWatcherKQueue() {}
+FilePathWatcherKQueue::~FilePathWatcherKQueue() {
+ DCHECK(!task_runner() || task_runner()->RunsTasksOnCurrentThread());
+}
void FilePathWatcherKQueue::ReleaseEvent(struct kevent& event) {
CloseFileDescriptor(&event.ident);
@@ -36,7 +38,6 @@ void FilePathWatcherKQueue::ReleaseEvent(struct kevent& event) {
}
int FilePathWatcherKQueue::EventsForPath(FilePath path, EventVector* events) {
- DCHECK(MessageLoopForIO::current());
// Make sure that we are working with a clean slate.
DCHECK(events->empty());
@@ -230,9 +231,74 @@ bool FilePathWatcherKQueue::UpdateWatches(bool* target_file_affected) {
return true;
}
-void FilePathWatcherKQueue::OnFileCanReadWithoutBlocking(int fd) {
- DCHECK(MessageLoopForIO::current());
- DCHECK_EQ(fd, kqueue_);
+bool FilePathWatcherKQueue::Watch(const FilePath& path,
+ bool recursive,
+ const FilePathWatcher::Callback& callback) {
+ DCHECK(target_.value().empty()); // Can only watch one path.
+ DCHECK(!callback.is_null());
+ DCHECK_EQ(kqueue_, -1);
+ // Recursive watch is not supported using kqueue.
+ DCHECK(!recursive);
+
+ callback_ = callback;
+ target_ = path;
+
+ set_task_runner(SequencedTaskRunnerHandle::Get());
+
+ kqueue_ = kqueue();
+ if (kqueue_ == -1) {
+ DPLOG(ERROR) << "kqueue";
+ return false;
+ }
+
+ int last_entry = EventsForPath(target_, &events_);
+ DCHECK_NE(last_entry, 0);
+
+ EventVector responses(last_entry);
+
+ int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry,
+ &responses[0], last_entry, NULL));
+ if (!AreKeventValuesValid(&responses[0], count)) {
+ // Calling Cancel() here to close any file descriptors that were opened.
+ // This would happen in the destructor anyways, but FilePathWatchers tend to
+ // be long lived, and if an error has occurred, there is no reason to waste
+ // the file descriptors.
+ Cancel();
+ return false;
+ }
+
+ // It's safe to use Unretained() because the watch is cancelled and the
+ // callback cannot be invoked after |kqueue_watch_controller_| (which is a
+ // member of |this|) has been deleted.
+ kqueue_watch_controller_ = FileDescriptorWatcher::WatchReadable(
+ kqueue_,
+ Bind(&FilePathWatcherKQueue::OnKQueueReadable, Unretained(this)));
+
+ return true;
+}
+
+void FilePathWatcherKQueue::Cancel() {
+ if (!task_runner()) {
+ set_cancelled();
+ return;
+ }
+
+ DCHECK(task_runner()->RunsTasksOnCurrentThread());
+ if (!is_cancelled()) {
+ set_cancelled();
+ kqueue_watch_controller_.reset();
+ if (IGNORE_EINTR(close(kqueue_)) != 0) {
+ DPLOG(ERROR) << "close kqueue";
+ }
+ kqueue_ = -1;
+ std::for_each(events_.begin(), events_.end(), ReleaseEvent);
+ events_.clear();
+ callback_.Reset();
+ }
+}
+
+void FilePathWatcherKQueue::OnKQueueReadable() {
+ DCHECK(task_runner()->RunsTasksOnCurrentThread());
DCHECK(events_.size());
// Request the file system update notifications that have occurred and return
@@ -303,89 +369,4 @@ void FilePathWatcherKQueue::OnFileCanReadWithoutBlocking(int fd) {
}
}
-void FilePathWatcherKQueue::OnFileCanWriteWithoutBlocking(int /* fd */) {
- NOTREACHED();
-}
-
-void FilePathWatcherKQueue::WillDestroyCurrentMessageLoop() {
- CancelOnMessageLoopThread();
-}
-
-bool FilePathWatcherKQueue::Watch(const FilePath& path,
- bool recursive,
- const FilePathWatcher::Callback& callback) {
- DCHECK(MessageLoopForIO::current());
- DCHECK(target_.value().empty()); // Can only watch one path.
- DCHECK(!callback.is_null());
- DCHECK_EQ(kqueue_, -1);
-
- if (recursive) {
- // Recursive watch is not supported using kqueue.
- NOTIMPLEMENTED();
- return false;
- }
-
- callback_ = callback;
- target_ = path;
-
- MessageLoop::current()->AddDestructionObserver(this);
- io_task_runner_ = ThreadTaskRunnerHandle::Get();
-
- kqueue_ = kqueue();
- if (kqueue_ == -1) {
- DPLOG(ERROR) << "kqueue";
- return false;
- }
-
- int last_entry = EventsForPath(target_, &events_);
- DCHECK_NE(last_entry, 0);
-
- EventVector responses(last_entry);
-
- int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry,
- &responses[0], last_entry, NULL));
- if (!AreKeventValuesValid(&responses[0], count)) {
- // Calling Cancel() here to close any file descriptors that were opened.
- // This would happen in the destructor anyways, but FilePathWatchers tend to
- // be long lived, and if an error has occurred, there is no reason to waste
- // the file descriptors.
- Cancel();
- return false;
- }
-
- return MessageLoopForIO::current()->WatchFileDescriptor(
- kqueue_, true, MessageLoopForIO::WATCH_READ, &kqueue_watcher_, this);
-}
-
-void FilePathWatcherKQueue::Cancel() {
- SingleThreadTaskRunner* task_runner = io_task_runner_.get();
- if (!task_runner) {
- set_cancelled();
- return;
- }
- if (!task_runner->BelongsToCurrentThread()) {
- task_runner->PostTask(FROM_HERE,
- base::Bind(&FilePathWatcherKQueue::Cancel, this));
- return;
- }
- CancelOnMessageLoopThread();
-}
-
-void FilePathWatcherKQueue::CancelOnMessageLoopThread() {
- DCHECK(MessageLoopForIO::current());
- if (!is_cancelled()) {
- set_cancelled();
- kqueue_watcher_.StopWatchingFileDescriptor();
- if (IGNORE_EINTR(close(kqueue_)) != 0) {
- DPLOG(ERROR) << "close kqueue";
- }
- kqueue_ = -1;
- std::for_each(events_.begin(), events_.end(), ReleaseEvent);
- events_.clear();
- io_task_runner_ = NULL;
- MessageLoop::current()->RemoveDestructionObserver(this);
- callback_.Reset();
- }
-}
-
} // namespace base