| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/files/file_path_watcher_kqueue.h" | 5 #include "base/files/file_path_watcher_kqueue.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <sys/param.h> | 8 #include <sys/param.h> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/sequenced_task_runner.h" |
| 13 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 15 #include "base/thread_task_runner_handle.h" |
| 14 | 16 |
| 15 // On some platforms these are not defined. | 17 // On some platforms these are not defined. |
| 16 #if !defined(EV_RECEIPT) | 18 #if !defined(EV_RECEIPT) |
| 17 #define EV_RECEIPT 0 | 19 #define EV_RECEIPT 0 |
| 18 #endif | 20 #endif |
| 19 #if !defined(O_EVTONLY) | 21 #if !defined(O_EVTONLY) |
| 20 #define O_EVTONLY O_RDONLY | 22 #define O_EVTONLY O_RDONLY |
| 21 #endif | 23 #endif |
| 22 | 24 |
| 23 namespace base { | 25 namespace base { |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 if (recursive) { | 322 if (recursive) { |
| 321 // Recursive watch is not supported using kqueue. | 323 // Recursive watch is not supported using kqueue. |
| 322 NOTIMPLEMENTED(); | 324 NOTIMPLEMENTED(); |
| 323 return false; | 325 return false; |
| 324 } | 326 } |
| 325 | 327 |
| 326 callback_ = callback; | 328 callback_ = callback; |
| 327 target_ = path; | 329 target_ = path; |
| 328 | 330 |
| 329 MessageLoop::current()->AddDestructionObserver(this); | 331 MessageLoop::current()->AddDestructionObserver(this); |
| 330 io_message_loop_ = base::MessageLoopProxy::current(); | 332 io_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 331 | 333 |
| 332 kqueue_ = kqueue(); | 334 kqueue_ = kqueue(); |
| 333 if (kqueue_ == -1) { | 335 if (kqueue_ == -1) { |
| 334 DPLOG(ERROR) << "kqueue"; | 336 DPLOG(ERROR) << "kqueue"; |
| 335 return false; | 337 return false; |
| 336 } | 338 } |
| 337 | 339 |
| 338 int last_entry = EventsForPath(target_, &events_); | 340 int last_entry = EventsForPath(target_, &events_); |
| 339 DCHECK_NE(last_entry, 0); | 341 DCHECK_NE(last_entry, 0); |
| 340 | 342 |
| 341 EventVector responses(last_entry); | 343 EventVector responses(last_entry); |
| 342 | 344 |
| 343 int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry, | 345 int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry, |
| 344 &responses[0], last_entry, NULL)); | 346 &responses[0], last_entry, NULL)); |
| 345 if (!AreKeventValuesValid(&responses[0], count)) { | 347 if (!AreKeventValuesValid(&responses[0], count)) { |
| 346 // Calling Cancel() here to close any file descriptors that were opened. | 348 // Calling Cancel() here to close any file descriptors that were opened. |
| 347 // This would happen in the destructor anyways, but FilePathWatchers tend to | 349 // This would happen in the destructor anyways, but FilePathWatchers tend to |
| 348 // be long lived, and if an error has occurred, there is no reason to waste | 350 // be long lived, and if an error has occurred, there is no reason to waste |
| 349 // the file descriptors. | 351 // the file descriptors. |
| 350 Cancel(); | 352 Cancel(); |
| 351 return false; | 353 return false; |
| 352 } | 354 } |
| 353 | 355 |
| 354 return MessageLoopForIO::current()->WatchFileDescriptor( | 356 return MessageLoopForIO::current()->WatchFileDescriptor( |
| 355 kqueue_, true, MessageLoopForIO::WATCH_READ, &kqueue_watcher_, this); | 357 kqueue_, true, MessageLoopForIO::WATCH_READ, &kqueue_watcher_, this); |
| 356 } | 358 } |
| 357 | 359 |
| 358 void FilePathWatcherKQueue::Cancel() { | 360 void FilePathWatcherKQueue::Cancel() { |
| 359 base::MessageLoopProxy* proxy = io_message_loop_.get(); | 361 base::SequencedTaskRunner* task_runner = io_task_runner_.get(); |
| 360 if (!proxy) { | 362 if (!task_runner) { |
| 361 set_cancelled(); | 363 set_cancelled(); |
| 362 return; | 364 return; |
| 363 } | 365 } |
| 364 if (!proxy->BelongsToCurrentThread()) { | 366 if (!task_runner->RunsTasksOnCurrentThread()) { |
| 365 proxy->PostTask(FROM_HERE, | 367 task_runner->PostTask(FROM_HERE, |
| 366 base::Bind(&FilePathWatcherKQueue::Cancel, this)); | 368 base::Bind(&FilePathWatcherKQueue::Cancel, this)); |
| 367 return; | 369 return; |
| 368 } | 370 } |
| 369 CancelOnMessageLoopThread(); | 371 CancelOnMessageLoopThread(); |
| 370 } | 372 } |
| 371 | 373 |
| 372 void FilePathWatcherKQueue::CancelOnMessageLoopThread() { | 374 void FilePathWatcherKQueue::CancelOnMessageLoopThread() { |
| 373 DCHECK(MessageLoopForIO::current()); | 375 DCHECK(MessageLoopForIO::current()); |
| 374 if (!is_cancelled()) { | 376 if (!is_cancelled()) { |
| 375 set_cancelled(); | 377 set_cancelled(); |
| 376 kqueue_watcher_.StopWatchingFileDescriptor(); | 378 kqueue_watcher_.StopWatchingFileDescriptor(); |
| 377 if (IGNORE_EINTR(close(kqueue_)) != 0) { | 379 if (IGNORE_EINTR(close(kqueue_)) != 0) { |
| 378 DPLOG(ERROR) << "close kqueue"; | 380 DPLOG(ERROR) << "close kqueue"; |
| 379 } | 381 } |
| 380 kqueue_ = -1; | 382 kqueue_ = -1; |
| 381 std::for_each(events_.begin(), events_.end(), ReleaseEvent); | 383 std::for_each(events_.begin(), events_.end(), ReleaseEvent); |
| 382 events_.clear(); | 384 events_.clear(); |
| 383 io_message_loop_ = NULL; | 385 io_task_runner_ = NULL; |
| 384 MessageLoop::current()->RemoveDestructionObserver(this); | 386 MessageLoop::current()->RemoveDestructionObserver(this); |
| 385 callback_.Reset(); | 387 callback_.Reset(); |
| 386 } | 388 } |
| 387 } | 389 } |
| 388 | 390 |
| 389 } // namespace base | 391 } // namespace base |
| OLD | NEW |