Index: mojo/edk/system/wait_set_dispatcher.cc |
diff --git a/mojo/edk/system/wait_set_dispatcher.cc b/mojo/edk/system/wait_set_dispatcher.cc |
index 7d59f32a90cb2426b3c5da0098812021f5b62b34..a083ce961b3804640e55c06488af09a7f44c9ec9 100644 |
--- a/mojo/edk/system/wait_set_dispatcher.cc |
+++ b/mojo/edk/system/wait_set_dispatcher.cc |
@@ -246,6 +246,12 @@ MojoResult WaitSetDispatcher::AddAwakable(Awakable* awakable, |
uintptr_t context, |
HandleSignalsState* signals_state) { |
base::AutoLock lock(lock_); |
+ // |awakable_lock_| is acquired here instead of immediately before adding to |
+ // |awakable_list_| because we need to check the signals state and add to |
+ // |awakable_list_| as an atomic operation. If the pair isn't atomic, it is |
+ // possible for the signals state to change after it is checked, but before |
+ // the awakable is added. In that case, the added awakable won't be signalled. |
+ base::AutoLock awakable_locker(awakable_lock_); |
HandleSignalsState state(GetHandleSignalsStateNoLock()); |
if (state.satisfies(signals)) { |
if (signals_state) |
@@ -258,7 +264,6 @@ MojoResult WaitSetDispatcher::AddAwakable(Awakable* awakable, |
return MOJO_RESULT_FAILED_PRECONDITION; |
} |
- base::AutoLock locker(awakable_lock_); |
awakable_list_.Add(awakable, signals, context); |
return MOJO_RESULT_OK; |
} |