| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/directory_watcher.h" | 5 #include "base/directory_watcher.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 #include <sys/inotify.h> | 9 #include <sys/inotify.h> |
| 10 #include <sys/ioctl.h> | 10 #include <sys/ioctl.h> |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 return (inotify_rm_watch(inotify_fd_, watch) == 0); | 324 return (inotify_rm_watch(inotify_fd_, watch) == 0); |
| 325 } | 325 } |
| 326 | 326 |
| 327 return true; | 327 return true; |
| 328 } | 328 } |
| 329 | 329 |
| 330 void InotifyReader::OnInotifyEvent(const inotify_event* event) { | 330 void InotifyReader::OnInotifyEvent(const inotify_event* event) { |
| 331 if (event->mask & IN_IGNORED) | 331 if (event->mask & IN_IGNORED) |
| 332 return; | 332 return; |
| 333 | 333 |
| 334 WatcherSet watchers_to_notify; | 334 // In case you want to limit the scope of this lock, it's not sufficient |
| 335 FilePath changed_path; | 335 // to just copy things under the lock, and then run the notifications |
| 336 // without holding the lock. DirectoryWatcherImpl's dtor removes its watches, |
| 337 // and to do that obtains the lock. After it finishes removing watches, |
| 338 // it's destroyed. So, if you copy under the lock and notify without the lock, |
| 339 // it's possible you'll copy the DirectoryWatcherImpl which is being |
| 340 // destroyed, then it will destroy itself, and then you'll try to notify it. |
| 341 AutoLock auto_lock(lock_); |
| 336 | 342 |
| 337 { | 343 for (WatcherSet::iterator watcher = watchers_[event->wd].begin(); |
| 338 AutoLock auto_lock(lock_); | 344 watcher != watchers_[event->wd].end(); |
| 339 changed_path = paths_[event->wd]; | |
| 340 watchers_to_notify.insert(watchers_[event->wd].begin(), | |
| 341 watchers_[event->wd].end()); | |
| 342 } | |
| 343 | |
| 344 for (WatcherSet::iterator watcher = watchers_to_notify.begin(); | |
| 345 watcher != watchers_to_notify.end(); | |
| 346 ++watcher) { | 345 ++watcher) { |
| 347 (*watcher)->OnInotifyEvent(event); | 346 (*watcher)->OnInotifyEvent(event); |
| 348 } | 347 } |
| 349 } | 348 } |
| 350 | 349 |
| 351 DirectoryWatcherImpl::DirectoryWatcherImpl() | 350 DirectoryWatcherImpl::DirectoryWatcherImpl() |
| 352 : watch_(InotifyReader::kInvalidWatch), | 351 : watch_(InotifyReader::kInvalidWatch), |
| 353 recursive_setup_finished_(false, false) { | 352 recursive_setup_finished_(false, false) { |
| 354 } | 353 } |
| 355 | 354 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 DirectoryWatcher::Delegate* delegate, | 430 DirectoryWatcher::Delegate* delegate, |
| 432 MessageLoop* backend_loop, bool recursive) { | 431 MessageLoop* backend_loop, bool recursive) { |
| 433 | 432 |
| 434 // Can only watch one path. | 433 // Can only watch one path. |
| 435 DCHECK(watch_ == InotifyReader::kInvalidWatch); | 434 DCHECK(watch_ == InotifyReader::kInvalidWatch); |
| 436 | 435 |
| 437 ino_t inode; | 436 ino_t inode; |
| 438 if (!file_util::GetInode(path, &inode)) | 437 if (!file_util::GetInode(path, &inode)) |
| 439 return false; | 438 return false; |
| 440 | 439 |
| 441 InotifyReader::Watch watch = | |
| 442 Singleton<InotifyReader>::get()->AddWatch(path, this); | |
| 443 if (watch == InotifyReader::kInvalidWatch) | |
| 444 return false; | |
| 445 | |
| 446 delegate_ = delegate; | 440 delegate_ = delegate; |
| 447 recursive_ = recursive; | 441 recursive_ = recursive; |
| 448 root_path_ = path; | 442 root_path_ = path; |
| 449 watch_ = watch; | |
| 450 loop_ = MessageLoop::current(); | 443 loop_ = MessageLoop::current(); |
| 444 watch_ = Singleton<InotifyReader>::get()->AddWatch(path, this); |
| 445 if (watch_ == InotifyReader::kInvalidWatch) |
| 446 return false; |
| 451 | 447 |
| 452 { | 448 { |
| 453 AutoLock auto_lock(lock_); | 449 AutoLock auto_lock(lock_); |
| 454 inodes_watched_.insert(inode); | 450 inodes_watched_.insert(inode); |
| 455 watches_.insert(watch_); | 451 watches_.insert(watch_); |
| 456 } | 452 } |
| 457 | 453 |
| 458 if (recursive_) { | 454 if (recursive_) { |
| 459 Task* subtree_task = new RegisterSubtreeWatchesTask(this, root_path_); | 455 Task* subtree_task = new RegisterSubtreeWatchesTask(this, root_path_); |
| 460 if (backend_loop) { | 456 if (backend_loop) { |
| 461 backend_loop->PostTask(FROM_HERE, subtree_task); | 457 backend_loop->PostTask(FROM_HERE, subtree_task); |
| 462 } else { | 458 } else { |
| 463 subtree_task->Run(); | 459 subtree_task->Run(); |
| 464 delete subtree_task; | 460 delete subtree_task; |
| 465 } | 461 } |
| 466 } | 462 } |
| 467 | 463 |
| 468 return true; | 464 return true; |
| 469 } | 465 } |
| 470 | 466 |
| 471 } // namespace | 467 } // namespace |
| 472 | 468 |
| 473 DirectoryWatcher::DirectoryWatcher() { | 469 DirectoryWatcher::DirectoryWatcher() { |
| 474 impl_ = new DirectoryWatcherImpl(); | 470 impl_ = new DirectoryWatcherImpl(); |
| 475 } | 471 } |
| 476 | |
| OLD | NEW |