aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2017-11-08 12:08:33 -0800
committerGravatar Craig Tiller <ctiller@google.com>2017-11-08 12:08:33 -0800
commit1ef989cd50cdfb172e99c552a67e3ed5f350e5cc (patch)
treeeb51f1aa91d6204122540f7fafd20f1f20612156
parent15626bb5274d4f0a65d9328af536b46f3a15e18b (diff)
Fixes, commentary
-rw-r--r--src/core/lib/iomgr/lockfree_event.cc25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc
index af1bee4694..40e2ed6219 100644
--- a/src/core/lib/iomgr/lockfree_event.cc
+++ b/src/core/lib/iomgr/lockfree_event.cc
@@ -58,16 +58,29 @@ extern grpc_tracer_flag grpc_polling_trace;
namespace grpc_core {
LockfreeEvent::LockfreeEvent() {
+ /* Perform an atomic store to start the state machine.
+
+ Note carefully that LockfreeEvent *MAY* be used whilst in a destroyed
+ state, while a file descriptor is on a freelist. In such a state it may
+ be SetReady'd, and so we need to perform an atomic operation here to
+ ensure no races */
gpr_atm_no_barrier_store(&state_, kClosureNotReady);
}
LockfreeEvent::~LockfreeEvent() {
- gpr_atm curr = gpr_atm_no_barrier_load(&state_);
- if (curr & kShutdownBit) {
- GRPC_ERROR_UNREF((grpc_error*)(curr & ~kShutdownBit));
- } else {
- GPR_ASSERT(curr == kClosureNotReady || curr == kClosureReady);
- }
+ gpr_atm curr;
+ do {
+ curr = gpr_atm_no_barrier_load(&state_);
+ if (curr & kShutdownBit) {
+ GRPC_ERROR_UNREF((grpc_error*)(curr & ~kShutdownBit));
+ } else {
+ GPR_ASSERT(curr == kClosureNotReady || curr == kClosureReady);
+ }
+ /* we CAS in a shutdown, no error value here. If this event is interacted
+ with post-deletion (see the note in the constructor) we want the bit
+ pattern to prevent error retention in a deleted object */
+ } while (!gpr_atm_no_barrier_cas(&state_, curr,
+ kShutdownBit /* shutdown, no error */));
}
void LockfreeEvent::NotifyOn(grpc_exec_ctx* exec_ctx, grpc_closure* closure) {