Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: base/directory_watcher_inotify.cc

Issue 149630: Fix two races in DirectoryWatcherInotify: (Closed)
Patch Set: Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698