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

Side by Side Diff: base/files/file_path_watcher_kqueue.cc

Issue 2517323002: Remove destruction observer from base::FilePathWatcherKQueue. (Closed)
Patch Set: document that this must be called from a thread that supports FileDescriptorWatcher Created 4 years 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 | « base/files/file_path_watcher_kqueue.h ('k') | 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) 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 <stddef.h> 8 #include <stddef.h>
9 #include <sys/param.h> 9 #include <sys/param.h>
10 10
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 *target_file_affected = true; 222 *target_file_affected = true;
223 } 223 }
224 } else { 224 } else {
225 break; 225 break;
226 } 226 }
227 } 227 }
228 } 228 }
229 return true; 229 return true;
230 } 230 }
231 231
232 void FilePathWatcherKQueue::WillDestroyCurrentMessageLoop() {
233 CancelOnMessageLoopThread();
234 }
235
236 bool FilePathWatcherKQueue::Watch(const FilePath& path, 232 bool FilePathWatcherKQueue::Watch(const FilePath& path,
237 bool recursive, 233 bool recursive,
238 const FilePathWatcher::Callback& callback) { 234 const FilePathWatcher::Callback& callback) {
239 DCHECK(target_.value().empty()); // Can only watch one path. 235 DCHECK(target_.value().empty()); // Can only watch one path.
240 DCHECK(!callback.is_null()); 236 DCHECK(!callback.is_null());
241 DCHECK_EQ(kqueue_, -1); 237 DCHECK_EQ(kqueue_, -1);
242 // Recursive watch is not supported using kqueue. 238 // Recursive watch is not supported using kqueue.
243 DCHECK(!recursive); 239 DCHECK(!recursive);
244 240
245 callback_ = callback; 241 callback_ = callback;
246 target_ = path; 242 target_ = path;
247 243
248 MessageLoop::current()->AddDestructionObserver(this);
249 set_task_runner(ThreadTaskRunnerHandle::Get()); 244 set_task_runner(ThreadTaskRunnerHandle::Get());
250 245
251 kqueue_ = kqueue(); 246 kqueue_ = kqueue();
252 if (kqueue_ == -1) { 247 if (kqueue_ == -1) {
253 DPLOG(ERROR) << "kqueue"; 248 DPLOG(ERROR) << "kqueue";
254 return false; 249 return false;
255 } 250 }
256 251
257 int last_entry = EventsForPath(target_, &events_); 252 int last_entry = EventsForPath(target_, &events_);
258 DCHECK_NE(last_entry, 0); 253 DCHECK_NE(last_entry, 0);
259 254
260 EventVector responses(last_entry); 255 EventVector responses(last_entry);
261 256
262 int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry, 257 int count = HANDLE_EINTR(kevent(kqueue_, &events_[0], last_entry,
263 &responses[0], last_entry, NULL)); 258 &responses[0], last_entry, NULL));
264 if (!AreKeventValuesValid(&responses[0], count)) { 259 if (!AreKeventValuesValid(&responses[0], count)) {
265 // Calling Cancel() here to close any file descriptors that were opened. 260 // Calling Cancel() here to close any file descriptors that were opened.
266 // This would happen in the destructor anyways, but FilePathWatchers tend to 261 // This would happen in the destructor anyways, but FilePathWatchers tend to
267 // be long lived, and if an error has occurred, there is no reason to waste 262 // be long lived, and if an error has occurred, there is no reason to waste
268 // the file descriptors. 263 // the file descriptors.
269 Cancel(); 264 Cancel();
270 return false; 265 return false;
271 } 266 }
272 267
273 // This creates an ownership cycle (|this| owns |kqueue_watch_controller_| 268 // This creates an ownership cycle (|this| owns |kqueue_watch_controller_|
274 // which owns a callback which owns |this|). The cycle is broken when 269 // which owns a callback which owns |this|). The cycle is broken when
275 // |kqueue_watch_controller_| is reset in CancelOnMessageLoopThread(). 270 // |kqueue_watch_controller_| is reset in Cancel().
276 kqueue_watch_controller_ = FileDescriptorWatcher::WatchReadable( 271 kqueue_watch_controller_ = FileDescriptorWatcher::WatchReadable(
277 kqueue_, Bind(&FilePathWatcherKQueue::OnKQueueReadable, this)); 272 kqueue_, Bind(&FilePathWatcherKQueue::OnKQueueReadable, this));
278 return true; 273 return true;
279 } 274 }
280 275
281 void FilePathWatcherKQueue::Cancel() { 276 void FilePathWatcherKQueue::Cancel() {
282 if (!task_runner()) { 277 if (!task_runner()) {
283 set_cancelled(); 278 set_cancelled();
284 return; 279 return;
285 } 280 }
286 if (!task_runner()->BelongsToCurrentThread()) { 281
287 task_runner()->PostTask(FROM_HERE, 282 DCHECK(task_runner()->BelongsToCurrentThread());
288 base::Bind(&FilePathWatcherKQueue::Cancel, this)); 283 if (!is_cancelled()) {
289 return; 284 set_cancelled();
285 kqueue_watch_controller_.reset();
286 if (IGNORE_EINTR(close(kqueue_)) != 0) {
287 DPLOG(ERROR) << "close kqueue";
288 }
289 kqueue_ = -1;
290 std::for_each(events_.begin(), events_.end(), ReleaseEvent);
291 events_.clear();
292 callback_.Reset();
290 } 293 }
291 CancelOnMessageLoopThread();
292 } 294 }
293 295
294 void FilePathWatcherKQueue::OnKQueueReadable() { 296 void FilePathWatcherKQueue::OnKQueueReadable() {
295 DCHECK(task_runner()->BelongsToCurrentThread()); 297 DCHECK(task_runner()->BelongsToCurrentThread());
296 DCHECK(events_.size()); 298 DCHECK(events_.size());
297 299
298 // Request the file system update notifications that have occurred and return 300 // Request the file system update notifications that have occurred and return
299 // them in |updates|. |count| will contain the number of updates that have 301 // them in |updates|. |count| will contain the number of updates that have
300 // occurred. 302 // occurred.
301 EventVector updates(events_.size()); 303 EventVector updates(events_.size());
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 callback_.Run(target_, true /* error */); 358 callback_.Run(target_, true /* error */);
357 Cancel(); 359 Cancel();
358 } 360 }
359 } 361 }
360 362
361 if (send_notification) { 363 if (send_notification) {
362 callback_.Run(target_, false); 364 callback_.Run(target_, false);
363 } 365 }
364 } 366 }
365 367
366 void FilePathWatcherKQueue::CancelOnMessageLoopThread() {
367 DCHECK(!task_runner() || task_runner()->BelongsToCurrentThread());
368 if (!is_cancelled()) {
369 set_cancelled();
370 kqueue_watch_controller_.reset();
371 if (IGNORE_EINTR(close(kqueue_)) != 0) {
372 DPLOG(ERROR) << "close kqueue";
373 }
374 kqueue_ = -1;
375 std::for_each(events_.begin(), events_.end(), ReleaseEvent);
376 events_.clear();
377 MessageLoop::current()->RemoveDestructionObserver(this);
378 callback_.Reset();
379 }
380 }
381
382 } // namespace base 368 } // namespace base
OLDNEW
« no previous file with comments | « base/files/file_path_watcher_kqueue.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698