aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2016-03-07 10:14:48 -0800
committerGravatar Craig Tiller <ctiller@google.com>2016-03-07 10:14:48 -0800
commitf880e62e04319c92caf361bc6d6a308209a56938 (patch)
treea078ecad5d74ab2ff9141c54dd0d4724e2a0c6c4
parent6537ab9dc12607307338be1ab3c7b10b91e4a1f4 (diff)
Potential fix for race condition exposed by Node
-rw-r--r--src/core/channel/subchannel_call_holder.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/src/core/channel/subchannel_call_holder.c b/src/core/channel/subchannel_call_holder.c
index 81297c8d44..0f765c218b 100644
--- a/src/core/channel/subchannel_call_holder.c
+++ b/src/core/channel/subchannel_call_holder.c
@@ -168,21 +168,24 @@ retry:
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
grpc_subchannel_call_holder *holder = arg;
- grpc_subchannel_call *call;
gpr_mu_lock(&holder->mu);
GPR_ASSERT(holder->creation_phase ==
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
- call = GET_CALL(holder);
- GPR_ASSERT(call == NULL || call == CANCELLED_CALL);
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
if (holder->connected_subchannel == NULL) {
fail_locked(exec_ctx, holder);
} else {
- gpr_atm_rel_store(
+ if (!gpr_atm_rel_cas(
&holder->subchannel_call,
+ 0,
(gpr_atm)(uintptr_t)grpc_connected_subchannel_create_call(
- exec_ctx, holder->connected_subchannel, holder->pollset));
- retry_waiting_locked(exec_ctx, holder);
+ exec_ctx, holder->connected_subchannel, holder->pollset))) {
+ GPR_ASSERT(gpr_atm_acq_load(&holder->subchannel_call) == 1);
+ /* if this cas fails, the call was cancelled before the pick completed */
+ fail_locked(exec_ctx, holder);
+ } else {
+ retry_waiting_locked(exec_ctx, holder);
+ }
}
gpr_mu_unlock(&holder->mu);
GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");