Index: base/synchronization/waitable_event_watcher_win.cc |
diff --git a/base/synchronization/waitable_event_watcher_win.cc b/base/synchronization/waitable_event_watcher_win.cc |
index f3e114e3966149c610d5579ec69fddaf32555c5f..d28b6a765743cc2cc41d49790be1ca1d0afd58ab 100644 |
--- a/base/synchronization/waitable_event_watcher_win.cc |
+++ b/base/synchronization/waitable_event_watcher_win.cc |
@@ -12,26 +12,43 @@ namespace base { |
WaitableEventWatcher::WaitableEventWatcher() = default; |
-WaitableEventWatcher::~WaitableEventWatcher() { |
-} |
+WaitableEventWatcher::~WaitableEventWatcher() {} |
bool WaitableEventWatcher::StartWatching(WaitableEvent* event, |
EventCallback callback) { |
+ DCHECK(event); |
callback_ = std::move(callback); |
event_ = event; |
- return watcher_.StartWatchingOnce(event->handle(), this); |
+ |
+ // Duplicate and hold the event handle until a callback is returned or |
+ // waiting is stopped. |
+ HANDLE handle = nullptr; |
+ if (!::DuplicateHandle(::GetCurrentProcess(), // hSourceProcessHandle |
+ event->handle(), |
+ ::GetCurrentProcess(), // hTargetProcessHandle |
+ &handle, |
+ 0, // dwDesiredAccess ignored due to SAME_ACCESS |
+ FALSE, // !bInheritHandle |
+ DUPLICATE_SAME_ACCESS)) { |
+ return false; |
+ } |
+ duplicated_event_handle_.Set(handle); |
+ return watcher_.StartWatchingOnce(handle, this); |
} |
void WaitableEventWatcher::StopWatching() { |
callback_.Reset(); |
event_ = NULL; |
watcher_.StopWatching(); |
+ duplicated_event_handle_.Close(); |
} |
void WaitableEventWatcher::OnObjectSignaled(HANDLE h) { |
+ DCHECK_EQ(duplicated_event_handle_.Get(), h); |
WaitableEvent* event = event_; |
EventCallback callback = std::move(callback_); |
event_ = NULL; |
+ duplicated_event_handle_.Close(); |
DCHECK(event); |
std::move(callback).Run(event); |