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/files/file_util.h" | 11 #include "base/files/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 |