aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/channel/client_channel.c
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-06-02 08:15:33 -0700
committerGravatar Craig Tiller <ctiller@google.com>2015-06-02 08:15:33 -0700
commitf93fd05a97081626dbd78c4553b6c2e78eeba920 (patch)
treed50c33113c3c09618527944f29738accb741225a /src/core/channel/client_channel.c
parent3a862e3b1047a081061d5ea207a7db3ec47a2e6d (diff)
Fix use-after-free
Diffstat (limited to 'src/core/channel/client_channel.c')
-rw-r--r--src/core/channel/client_channel.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c
index ac34851504..1eda23b791 100644
--- a/src/core/channel/client_channel.c
+++ b/src/core/channel/client_channel.c
@@ -372,12 +372,24 @@ static void init_call_elem(grpc_call_element *elem,
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) {
call_data *calld = elem->call_data;
+ channel_data *chand = elem->channel_data;
/* if the call got activated, we need to destroy the child stack also, and
remove it from the in-flight requests tracked by the child_entry we
picked */
- if (calld->state == CALL_ACTIVE) {
- grpc_child_call_destroy(calld->s.active.child_call);
+ gpr_mu_lock(&chand->mu);
+ switch (calld->state) {
+ case CALL_ACTIVE:
+ gpr_mu_unlock(&chand->mu);
+ grpc_child_call_destroy(calld->s.active.child_call);
+ break;
+ case CALL_WAITING:
+ remove_waiting_child(chand, calld);
+ gpr_mu_unlock(&chand->mu);
+ break;
+ default:
+ gpr_mu_unlock(&chand->mu);
+ break;
}
GPR_ASSERT(calld->state != CALL_WAITING);
}