Index: base/waitable_event_watcher_posix.cc |
diff --git a/base/waitable_event_watcher_posix.cc b/base/waitable_event_watcher_posix.cc |
index e4e1a7f08f1a1243db2195edb229d2f711d56994..10d47b7cc37839965bfbf8259c0a9d724ce4e303 100644 |
--- a/base/waitable_event_watcher_posix.cc |
+++ b/base/waitable_event_watcher_posix.cc |
@@ -80,6 +80,7 @@ class AsyncWaiter : public WaitableEvent::Waiter { |
return tag == flag_.get(); |
} |
+ private: |
MessageLoop *const message_loop_; |
Task *const cb_task_; |
scoped_refptr<Flag> flag_; |
@@ -101,12 +102,12 @@ class AsyncCallbackTask : public Task { |
void Run() { |
// Runs in MessageLoop thread. |
- if (!flag_->value()) |
+ if (!flag_->value()) { |
+ // This is to let the WaitableEventWatcher know that the event has occured |
+ // because it needs to be able to return NULL from GetWatchedObject |
+ flag_->Set(); |
delegate_->OnWaitableEventSignaled(event_); |
- |
- // This is to let the WaitableEventWatcher know that the event has occured |
- // because it needs to be able to return NULL from GetWatchedEvent |
- flag_->Set(); |
+ } |
// We are deleted by the MessageLoop |
} |
@@ -138,6 +139,18 @@ bool WaitableEventWatcher::StartWatching |
DCHECK(current_ml) << "Cannot create WaitableEventWatcher without a " |
"current MessageLoop"; |
+ // A user may call StartWatching from within the callback function. In this |
+ // case, we won't know that we have finished watching, expect that the Flag |
+ // will have been set in AsyncCallbackTask::Run() |
+ if (cancel_flag_.get() && cancel_flag_->value()) { |
+ if (message_loop_) { |
+ message_loop_->RemoveDestructionObserver(this); |
+ message_loop_ = NULL; |
+ } |
+ |
+ cancel_flag_ = NULL; |
+ } |
+ |
DCHECK(!cancel_flag_.get()) << "StartWatching called while still watching"; |
cancel_flag_ = new Flag; |
@@ -174,6 +187,13 @@ void WaitableEventWatcher::StopWatching() { |
if (!cancel_flag_.get()) // if not currently watching... |
return; |
+ if (cancel_flag_->value()) { |
+ // In this case, the event has fired, but we haven't figured that out yet. |
+ // The WaitableEvent may have been deleted too. |
+ cancel_flag_ = NULL; |
+ return; |
+ } |
+ |
if (!event_) { |
// We have no WaitableEvent. This means that we never enqueued a Waiter on |
// an event because the event was already signaled when StartWatching was |