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