|  | @@ -386,10 +386,18 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
 | 
	
		
			
				|  |  |    for (s = shard->strs[idx]; s; s = s->bucket_next) {
 | 
	
		
			
				|  |  |      if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length &&
 | 
	
		
			
				|  |  |          0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) {
 | 
	
		
			
				|  |  | -      GRPC_MDSTR_REF((grpc_mdstr *)s);
 | 
	
		
			
				|  |  | -      gpr_mu_unlock(&shard->mu);
 | 
	
		
			
				|  |  | -      GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
 | 
	
		
			
				|  |  | -      return (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_TIMER_END("grpc_mdstr_from_buffer", 0);
 | 
	
		
			
				|  |  | +        return (grpc_mdstr *)s;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -397,7 +405,7 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
 | 
	
		
			
				|  |  |    if (length + 1 < GPR_SLICE_INLINED_SIZE) {
 | 
	
		
			
				|  |  |      /* string data goes directly into the slice */
 | 
	
		
			
				|  |  |      s = gpr_malloc(sizeof(internal_string));
 | 
	
		
			
				|  |  | -    gpr_atm_rel_store(&s->refcnt, 2);
 | 
	
		
			
				|  |  | +    gpr_atm_rel_store(&s->refcnt, 1);
 | 
	
		
			
				|  |  |      s->slice.refcount = NULL;
 | 
	
		
			
				|  |  |      memcpy(s->slice.data.inlined.bytes, buf, length);
 | 
	
		
			
				|  |  |      s->slice.data.inlined.bytes[length] = 0;
 | 
	
	
		
			
				|  | @@ -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
 | 
	
		
			
				|  |  |         terminator */
 | 
	
		
			
				|  |  |      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.unref = slice_unref;
 | 
	
		
			
				|  |  |      s->slice.refcount = &s->refcount;
 | 
	
	
		
			
				|  | @@ -675,20 +683,19 @@ const char *grpc_mdstr_as_c_string(grpc_mdstr *s) {
 | 
	
		
			
				|  |  |  grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
 | 
	
		
			
				|  |  |    internal_string *s = (internal_string *)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;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) {
 | 
	
		
			
				|  |  |    internal_string *s = (internal_string *)gs;
 | 
	
		
			
				|  |  |    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 =
 | 
	
		
			
				|  |  |          &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
 | 
	
		
			
				|  |  |      gpr_mu_lock(&shard->mu);
 | 
	
		
			
				|  |  | -    if (1 == gpr_atm_no_barrier_load(&s->refcnt)) {
 | 
	
		
			
				|  |  | -      internal_destroy_string(shard, s);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt));
 | 
	
		
			
				|  |  | +    internal_destroy_string(shard, s);
 | 
	
		
			
				|  |  |      gpr_mu_unlock(&shard->mu);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 |