aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/transport/metadata.c
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-02-18 14:16:15 -0800
committerGravatar Craig Tiller <ctiller@google.com>2015-02-18 14:16:15 -0800
commit9be83eec1de2932946d61b774788ca18fb41e2fe (patch)
treef8672252e92ceff39ee7eccc571c31a33cf548eb /src/core/transport/metadata.c
parentefad8fadd36899ff98ff616c349d181f2f1e4004 (diff)
Fix use-after-free.
Transport and channel have different lifetimes, but share a metadata context. Make the metadata context ref counted, and have transport take a ref.
Diffstat (limited to 'src/core/transport/metadata.c')
-rw-r--r--src/core/transport/metadata.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c
index 3dc23e7de2..1c15716fad 100644
--- a/src/core/transport/metadata.c
+++ b/src/core/transport/metadata.c
@@ -79,7 +79,7 @@ typedef struct internal_metadata {
struct grpc_mdctx {
gpr_uint32 hash_seed;
- int orphaned;
+ int refs;
gpr_mu mu;
@@ -114,7 +114,7 @@ static void unlock(grpc_mdctx *ctx) {
mdelems on every unlock (instead of the usual 'I'm too loaded' trigger
case), since otherwise we can be stuck waiting for a garbage collection
that will never happen. */
- if (ctx->orphaned) {
+ 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); */
@@ -139,7 +139,7 @@ static void ref_md(internal_metadata *md) {
grpc_mdctx *grpc_mdctx_create_with_seed(gpr_uint32 seed) {
grpc_mdctx *ctx = gpr_malloc(sizeof(grpc_mdctx));
- ctx->orphaned = 0;
+ ctx->refs = 1;
ctx->hash_seed = seed;
gpr_mu_init(&ctx->mu);
ctx->strtab = gpr_malloc(sizeof(internal_string *) * INITIAL_STRTAB_CAPACITY);
@@ -197,10 +197,17 @@ static void metadata_context_destroy(grpc_mdctx *ctx) {
gpr_free(ctx);
}
-void grpc_mdctx_orphan(grpc_mdctx *ctx) {
+void grpc_mdctx_ref(grpc_mdctx *ctx) {
lock(ctx);
- GPR_ASSERT(!ctx->orphaned);
- ctx->orphaned = 1;
+ GPR_ASSERT(ctx->refs > 0);
+ ctx->refs++;
+ unlock(ctx);
+}
+
+void grpc_mdctx_unref(grpc_mdctx *ctx) {
+ lock(ctx);
+ GPR_ASSERT(ctx->refs > 0);
+ ctx->refs--;
unlock(ctx);
}