diff --git a/src/core/channel/client_channel.c b/src/core/channel/client_channel.c index 4daec40b944..bc481e59ca5 100644 --- a/src/core/channel/client_channel.c +++ b/src/core/channel/client_channel.c @@ -130,6 +130,7 @@ static void start_rpc(grpc_call_element *elem, grpc_call_op *op) { gpr_mu_lock(&chand->mu); if (calld->state == CALL_CANCELLED) { gpr_mu_unlock(&chand->mu); + grpc_metadata_batch_destroy(&op->data.metadata); op->done_cb(op->user_data, GRPC_OP_ERROR); return; } @@ -211,6 +212,7 @@ static void cancel_rpc(grpc_call_element *elem, grpc_call_op *op) { child_elem->filter->call_op(child_elem, elem, op); return; /* early out */ case CALL_WAITING: + grpc_metadata_batch_destroy(&calld->s.waiting_op.data.metadata); remove_waiting_child(chand, calld); calld->state = CALL_CANCELLED; gpr_mu_unlock(&chand->mu); @@ -370,6 +372,9 @@ static void destroy_call_elem(grpc_call_element *elem) { if (calld->state == CALL_ACTIVE) { grpc_child_call_destroy(calld->s.active.child_call); } + if (calld->state == CALL_WAITING) { + grpc_metadata_batch_destroy(&calld->s.waiting_op.data.metadata); + } } /* Constructor for channel_data */ diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c index 9bd148d9813..e47fa06ffcc 100644 --- a/src/core/channel/http_server_filter.c +++ b/src/core/channel/http_server_filter.c @@ -178,6 +178,7 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, gpr_log(GPR_ERROR, "Missing te trailers header"); } /* Error this call out */ + grpc_metadata_batch_destroy(&op->data.metadata); op->done_cb(op->user_data, GRPC_OP_OK); grpc_call_element_send_cancel(elem); } diff --git a/src/core/security/auth.c b/src/core/security/auth.c index 4acb7a4454e..1db29f2eeb9 100644 --- a/src/core/security/auth.c +++ b/src/core/security/auth.c @@ -144,6 +144,7 @@ static void on_host_checked(void *user_data, grpc_security_status status) { gpr_asprintf(&error_msg, "Invalid host %s set in :authority metadata.", grpc_mdstr_as_c_string(calld->host)); bubbleup_error(elem, error_msg); + grpc_metadata_batch_destroy(&calld->op.data.metadata); gpr_free(error_msg); calld->op.done_cb(calld->op.user_data, GRPC_OP_ERROR); } @@ -188,6 +189,7 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, "Invalid host %s set in :authority metadata.", call_host); bubbleup_error(elem, error_msg); + grpc_metadata_batch_destroy(&calld->op.data.metadata); gpr_free(error_msg); op->done_cb(op->user_data, GRPC_OP_ERROR); } diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 84d53c51dac..608442c0089 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -307,6 +307,9 @@ static void destroy_call(void *call, int ignored_success) { for (i = 0; i < GPR_ARRAY_SIZE(c->buffered_metadata); i++) { gpr_free(c->buffered_metadata[i].metadata); } + for (i = 0; i < c->send_initial_metadata_count; i++) { + grpc_mdelem_unref(c->send_initial_metadata[i].md); + } if (c->legacy_state) { destroy_legacy_state(c->legacy_state); } @@ -663,6 +666,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { grpc_metadata_batch_link_head(&op.data.metadata, &call->send_initial_metadata[i]); } + call->send_initial_metadata_count = 0; op.done_cb = finish_start_step; op.user_data = call; op.bind_pollset = grpc_cq_pollset(call->cq); diff --git a/src/core/surface/lame_client.c b/src/core/surface/lame_client.c index 710418f1d98..718d9b1fea8 100644 --- a/src/core/surface/lame_client.c +++ b/src/core/surface/lame_client.c @@ -52,6 +52,7 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, switch (op->type) { case GRPC_SEND_METADATA: + grpc_metadata_batch_destroy(&op->data.metadata); grpc_call_recv_synthetic_status(elem, GRPC_STATUS_UNKNOWN, "Rpc sent on a lame channel."); grpc_call_stream_closed(elem); break; diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c index 44f6591c955..74e94b2c248 100644 --- a/src/core/transport/metadata.c +++ b/src/core/transport/metadata.c @@ -120,7 +120,7 @@ static void unlock(grpc_mdctx *ctx) { if (ctx->refs == 0) { /* uncomment if you're having trouble diagnosing an mdelem leak to make things clearer (slows down destruction a lot, however) */ - /* gc_mdtab(ctx); */ + gc_mdtab(ctx); if (ctx->mdtab_count && ctx->mdtab_count == ctx->mdtab_free) { discard_metadata(ctx); } diff --git a/src/core/transport/stream_op.c b/src/core/transport/stream_op.c index f38f60a86be..f3e634d8532 100644 --- a/src/core/transport/stream_op.c +++ b/src/core/transport/stream_op.c @@ -79,7 +79,7 @@ void grpc_stream_ops_unref_owned_objects(grpc_stream_op *ops, size_t nops) { gpr_slice_unref(ops[i].data.slice); break; case GRPC_OP_METADATA: - /* grpc_mdelem_unref(ops[i].data.metadata); */ + grpc_metadata_batch_destroy(&ops[i].data.metadata); break; case GRPC_OP_FLOW_CTL_CB: ops[i].data.flow_ctl_cb.cb(ops[i].data.flow_ctl_cb.arg, GRPC_OP_ERROR);