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(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_slice_intern_shutdown(void) { for (size_t i = 0; i < SHARD_COUNT; i++) { slice_shard *shard = &g_shards[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 (interned_slice_refcount *s = shard->strs[j]; s; s = s->bucket_next) { char *text = grpc_dump_slice(materialize(s), GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "LEAKED: %s", text); gpr_free(text); } } if (grpc_iomgr_abort_on_leaks()) { abort(); } } gpr_free(shard->strs); } }
void grpc_iomgr_shutdown(void) { gpr_timespec shutdown_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN)); gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_iomgr_platform_flush(); gpr_mu_lock(&g_mu); g_shutdown = 1; while (g_root_object.next != &g_root_object) { if (gpr_time_cmp( gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time), gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) { if (g_root_object.next != &g_root_object) { gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed", count_objects()); } last_warning_time = gpr_now(GPR_CLOCK_REALTIME); } if (grpc_timer_check(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL)) { gpr_mu_unlock(&g_mu); grpc_exec_ctx_flush(&exec_ctx); gpr_mu_lock(&g_mu); continue; } if (g_root_object.next != &g_root_object) { gpr_timespec short_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN)); if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline)) { if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) { if (g_root_object.next != &g_root_object) { gpr_log(GPR_DEBUG, "Failed to free %d iomgr objects before shutdown deadline: " "memory leaks are likely", count_objects()); dump_objects("LEAKED"); if (grpc_iomgr_abort_on_leaks()) { abort(); } } break; } } } } gpr_mu_unlock(&g_mu); grpc_timer_list_shutdown(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx); /* ensure all threads have left g_mu */ gpr_mu_lock(&g_mu); gpr_mu_unlock(&g_mu); grpc_pollset_global_shutdown(); grpc_iomgr_platform_shutdown(); grpc_exec_ctx_global_shutdown(); gpr_mu_destroy(&g_mu); gpr_cv_destroy(&g_rcv); }