static void unlock(grpc_mdctx *ctx) { /* If the context has been orphaned we'd like to delete it soon. We check conditions in unlock as it signals the end of mutations on a context. We need to ensure all grpc_mdelem and grpc_mdstr elements have been deleted first. This is equivalent to saying that both tables have zero counts, which is equivalent to saying that strtab_count is zero (as mdelem's MUST reference an mdstr for their key and value slots). To encourage that to happen, we start discarding zero reference count 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->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); if (ctx->mdtab_count && ctx->mdtab_count == ctx->mdtab_free) { discard_metadata(ctx); } if (ctx->strtab_count == 0) { metadata_context_destroy_locked(ctx); return; } } gpr_mu_unlock(&ctx->mu); }
static void rehash_mdtab(grpc_mdctx *ctx) { if (ctx->mdtab_free > ctx->mdtab_capacity / 4) { gc_mdtab(ctx); } else { grow_mdtab(ctx); } }
void grpc_mdctx_global_shutdown(grpc_exec_ctx *exec_ctx) { for (size_t i = 0; i < SHARD_COUNT; i++) { mdtab_shard *shard = &g_shards[i]; gpr_mu_destroy(&shard->mu); gc_mdtab(exec_ctx, shard); /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */ if (shard->count != 0) { gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata elements were leaked", shard->count); if (grpc_iomgr_abort_on_leaks()) { abort(); } } gpr_free(shard->elems); } }
void grpc_mdctx_global_shutdown(void) { size_t i; for (i = 0; i < MDTAB_SHARD_COUNT; i++) { mdtab_shard *shard = &g_mdtab_shard[i]; gpr_mu_destroy(&shard->mu); gc_mdtab(shard); /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */ if (shard->count != 0) { gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata elements were leaked", shard->count); if (grpc_iomgr_abort_on_leaks()) { abort(); } } gpr_free(shard->elems); } for (i = 0; i < STRTAB_SHARD_COUNT; i++) { strtab_shard *shard = &g_strtab_shard[i]; gpr_mu_destroy(&shard->mu); /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */ if (shard->count != 0) { gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata strings were leaked", shard->count); for (size_t j = 0; j < shard->capacity; j++) { for (internal_string *s = shard->strs[j]; s; s = s->bucket_next) { gpr_log(GPR_DEBUG, "LEAKED: %s", grpc_mdstr_as_c_string((grpc_mdstr *)s)); } } if (grpc_iomgr_abort_on_leaks()) { abort(); } } gpr_free(shard->strs); } }
void grpc_mdctx_global_shutdown(void) { size_t i; for (i = 0; i < MDTAB_SHARD_COUNT; i++) { mdtab_shard *shard = &g_mdtab_shard[i]; gpr_mu_destroy(&shard->mu); gc_mdtab(shard); /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */ if (shard->count != 0) { gpr_log(GPR_DEBUG, "WARNING: %d metadata elements were leaked", shard->count); } gpr_free(shard->elems); } for (i = 0; i < STRTAB_SHARD_COUNT; i++) { strtab_shard *shard = &g_strtab_shard[i]; gpr_mu_destroy(&shard->mu); /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */ if (shard->count != 0) { gpr_log(GPR_DEBUG, "WARNING: %d metadata strings were leaked", shard->count); } gpr_free(shard->strs); } }