Skip to content
Snippets Groups Projects
Commit 773d9908 authored by Craig Tiller's avatar Craig Tiller
Browse files

Fix refcounting bug for mdstrs

parent eeef86ce
No related branches found
No related tags found
No related merge requests found
...@@ -386,18 +386,26 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) { ...@@ -386,18 +386,26 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
for (s = shard->strs[idx]; s; s = s->bucket_next) { for (s = shard->strs[idx]; s; s = s->bucket_next) {
if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length && if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length &&
0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) { 0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) {
GRPC_MDSTR_REF((grpc_mdstr *)s); if (gpr_atm_full_fetch_add(&s->refcnt, 1) == 0) {
/* If we get here, we've added a ref to something that was about to
* die - drop it immediately.
* The *only* possible path here (given the shard mutex) should be to
* drop from one ref back to zero - assert that with a CAS */
GPR_ASSERT(gpr_atm_rel_cas(&s->refcnt, 1, 0));
/* and treat this as if we were never here... sshhh */
} else {
gpr_mu_unlock(&shard->mu); gpr_mu_unlock(&shard->mu);
GPR_TIMER_END("grpc_mdstr_from_buffer", 0); GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
return (grpc_mdstr *)s; return (grpc_mdstr *)s;
} }
} }
}
/* not found: create a new string */ /* not found: create a new string */
if (length + 1 < GPR_SLICE_INLINED_SIZE) { if (length + 1 < GPR_SLICE_INLINED_SIZE) {
/* string data goes directly into the slice */ /* string data goes directly into the slice */
s = gpr_malloc(sizeof(internal_string)); s = gpr_malloc(sizeof(internal_string));
gpr_atm_rel_store(&s->refcnt, 2); gpr_atm_rel_store(&s->refcnt, 1);
s->slice.refcount = NULL; s->slice.refcount = NULL;
memcpy(s->slice.data.inlined.bytes, buf, length); memcpy(s->slice.data.inlined.bytes, buf, length);
s->slice.data.inlined.bytes[length] = 0; s->slice.data.inlined.bytes[length] = 0;
...@@ -406,7 +414,7 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) { ...@@ -406,7 +414,7 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
/* string data goes after the internal_string header, and we +1 for null /* string data goes after the internal_string header, and we +1 for null
terminator */ terminator */
s = gpr_malloc(sizeof(internal_string) + length + 1); s = gpr_malloc(sizeof(internal_string) + length + 1);
gpr_atm_rel_store(&s->refcnt, 2); gpr_atm_rel_store(&s->refcnt, 1);
s->refcount.ref = slice_ref; s->refcount.ref = slice_ref;
s->refcount.unref = slice_unref; s->refcount.unref = slice_unref;
s->slice.refcount = &s->refcount; s->slice.refcount = &s->refcount;
...@@ -675,20 +683,19 @@ const char *grpc_mdstr_as_c_string(grpc_mdstr *s) { ...@@ -675,20 +683,19 @@ const char *grpc_mdstr_as_c_string(grpc_mdstr *s) {
grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) { grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
internal_string *s = (internal_string *)gs; internal_string *s = (internal_string *)gs;
if (is_mdstr_static(gs)) return gs; if (is_mdstr_static(gs)) return gs;
GPR_ASSERT(gpr_atm_full_fetch_add(&s->refcnt, 1) != 0); GPR_ASSERT(gpr_atm_full_fetch_add(&s->refcnt, 1) > 0);
return gs; return gs;
} }
void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) { void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) {
internal_string *s = (internal_string *)gs; internal_string *s = (internal_string *)gs;
if (is_mdstr_static(gs)) return; if (is_mdstr_static(gs)) return;
if (2 == gpr_atm_full_fetch_add(&s->refcnt, -1)) { if (1 == gpr_atm_full_fetch_add(&s->refcnt, -1)) {
strtab_shard *shard = strtab_shard *shard =
&g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)]; &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
gpr_mu_lock(&shard->mu); gpr_mu_lock(&shard->mu);
if (1 == gpr_atm_no_barrier_load(&s->refcnt)) { GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt));
internal_destroy_string(shard, s); internal_destroy_string(shard, s);
}
gpr_mu_unlock(&shard->mu); gpr_mu_unlock(&shard->mu);
} }
} }
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment