|
|
|
@ -33,6 +33,7 @@ |
|
|
|
|
#include "src/core/lib/debug/stats.h" |
|
|
|
|
#include "src/core/lib/debug/trace.h" |
|
|
|
|
#include "src/core/lib/gprpp/fork.h" |
|
|
|
|
#include "src/core/lib/gprpp/mutex_lock.h" |
|
|
|
|
#include "src/core/lib/http/parser.h" |
|
|
|
|
#include "src/core/lib/iomgr/call_combiner.h" |
|
|
|
|
#include "src/core/lib/iomgr/combiner.h" |
|
|
|
@ -61,10 +62,15 @@ extern void grpc_register_built_in_plugins(void); |
|
|
|
|
static gpr_once g_basic_init = GPR_ONCE_INIT; |
|
|
|
|
static gpr_mu g_init_mu; |
|
|
|
|
static int g_initializations; |
|
|
|
|
static gpr_cv* g_shutting_down_cv; |
|
|
|
|
static bool g_shutting_down; |
|
|
|
|
|
|
|
|
|
static void do_basic_init(void) { |
|
|
|
|
gpr_log_verbosity_init(); |
|
|
|
|
gpr_mu_init(&g_init_mu); |
|
|
|
|
g_shutting_down_cv = static_cast<gpr_cv*>(malloc(sizeof(gpr_cv))); |
|
|
|
|
gpr_cv_init(g_shutting_down_cv); |
|
|
|
|
g_shutting_down = false; |
|
|
|
|
grpc_register_built_in_plugins(); |
|
|
|
|
grpc_cq_global_init(); |
|
|
|
|
g_initializations = 0; |
|
|
|
@ -118,8 +124,12 @@ void grpc_init(void) { |
|
|
|
|
int i; |
|
|
|
|
gpr_once_init(&g_basic_init, do_basic_init); |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&g_init_mu); |
|
|
|
|
grpc_core::MutexLock lock(&g_init_mu); |
|
|
|
|
if (++g_initializations == 1) { |
|
|
|
|
if (g_shutting_down) { |
|
|
|
|
g_shutting_down = false; |
|
|
|
|
gpr_cv_broadcast(g_shutting_down_cv); |
|
|
|
|
} |
|
|
|
|
grpc_core::Fork::GlobalInit(); |
|
|
|
|
grpc_fork_handlers_auto_register(); |
|
|
|
|
gpr_time_init(); |
|
|
|
@ -150,50 +160,88 @@ void grpc_init(void) { |
|
|
|
|
grpc_channel_init_finalize(); |
|
|
|
|
grpc_iomgr_start(); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&g_init_mu); |
|
|
|
|
|
|
|
|
|
GRPC_API_TRACE("grpc_init(void)", 0, ()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_shutdown(void) { |
|
|
|
|
void grpc_shutdown_internal_locked(void) { |
|
|
|
|
int i; |
|
|
|
|
GRPC_API_TRACE("grpc_shutdown(void)", 0, ()); |
|
|
|
|
gpr_mu_lock(&g_init_mu); |
|
|
|
|
if (--g_initializations == 0) { |
|
|
|
|
{ |
|
|
|
|
grpc_core::ExecCtx exec_ctx(0); |
|
|
|
|
grpc_iomgr_shutdown_background_closure(); |
|
|
|
|
{ |
|
|
|
|
grpc_core::ExecCtx exec_ctx(0); |
|
|
|
|
grpc_iomgr_shutdown_background_closure(); |
|
|
|
|
{ |
|
|
|
|
grpc_timer_manager_set_threading( |
|
|
|
|
false); // shutdown timer_manager thread
|
|
|
|
|
grpc_core::Executor::ShutdownAll(); |
|
|
|
|
for (i = g_number_of_plugins; i >= 0; i--) { |
|
|
|
|
if (g_all_of_the_plugins[i].destroy != nullptr) { |
|
|
|
|
g_all_of_the_plugins[i].destroy(); |
|
|
|
|
} |
|
|
|
|
grpc_timer_manager_set_threading(false); // shutdown timer_manager thread
|
|
|
|
|
grpc_core::Executor::ShutdownAll(); |
|
|
|
|
for (i = g_number_of_plugins; i >= 0; i--) { |
|
|
|
|
if (g_all_of_the_plugins[i].destroy != nullptr) { |
|
|
|
|
g_all_of_the_plugins[i].destroy(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
grpc_iomgr_shutdown(); |
|
|
|
|
gpr_timers_global_destroy(); |
|
|
|
|
grpc_tracer_shutdown(); |
|
|
|
|
grpc_mdctx_global_shutdown(); |
|
|
|
|
grpc_core::HandshakerRegistry::Shutdown(); |
|
|
|
|
grpc_slice_intern_shutdown(); |
|
|
|
|
grpc_core::channelz::ChannelzRegistry::Shutdown(); |
|
|
|
|
grpc_stats_shutdown(); |
|
|
|
|
grpc_core::Fork::GlobalShutdown(); |
|
|
|
|
} |
|
|
|
|
grpc_core::ExecCtx::GlobalShutdown(); |
|
|
|
|
grpc_core::ApplicationCallbackExecCtx::GlobalShutdown(); |
|
|
|
|
grpc_iomgr_shutdown(); |
|
|
|
|
gpr_timers_global_destroy(); |
|
|
|
|
grpc_tracer_shutdown(); |
|
|
|
|
grpc_mdctx_global_shutdown(); |
|
|
|
|
grpc_core::HandshakerRegistry::Shutdown(); |
|
|
|
|
grpc_slice_intern_shutdown(); |
|
|
|
|
grpc_core::channelz::ChannelzRegistry::Shutdown(); |
|
|
|
|
grpc_stats_shutdown(); |
|
|
|
|
grpc_core::Fork::GlobalShutdown(); |
|
|
|
|
} |
|
|
|
|
grpc_core::ExecCtx::GlobalShutdown(); |
|
|
|
|
grpc_core::ApplicationCallbackExecCtx::GlobalShutdown(); |
|
|
|
|
g_shutting_down = false; |
|
|
|
|
gpr_cv_broadcast(g_shutting_down_cv); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_shutdown_internal(void* ignored) { |
|
|
|
|
GRPC_API_TRACE("grpc_shutdown_internal", 0, ()); |
|
|
|
|
grpc_core::MutexLock lock(&g_init_mu); |
|
|
|
|
// We have released lock from the shutdown thread and it is possible that
|
|
|
|
|
// another grpc_init has been called, and do nothing if that is the case.
|
|
|
|
|
if (--g_initializations != 0) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
grpc_shutdown_internal_locked(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_shutdown(void) { |
|
|
|
|
GRPC_API_TRACE("grpc_shutdown(void)", 0, ()); |
|
|
|
|
grpc_core::MutexLock lock(&g_init_mu); |
|
|
|
|
if (--g_initializations == 0) { |
|
|
|
|
g_initializations++; |
|
|
|
|
g_shutting_down = true; |
|
|
|
|
// spawn a detached thread to do the actual clean up in case we are
|
|
|
|
|
// currently in an executor thread.
|
|
|
|
|
grpc_core::Thread cleanup_thread( |
|
|
|
|
"grpc_shutdown", grpc_shutdown_internal, nullptr, nullptr, |
|
|
|
|
grpc_core::Thread::Options().set_joinable(false).set_tracked(false)); |
|
|
|
|
cleanup_thread.Start(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_shutdown_blocking(void) { |
|
|
|
|
GRPC_API_TRACE("grpc_shutdown_blocking(void)", 0, ()); |
|
|
|
|
grpc_core::MutexLock lock(&g_init_mu); |
|
|
|
|
if (--g_initializations == 0) { |
|
|
|
|
g_shutting_down = true; |
|
|
|
|
grpc_shutdown_internal_locked(); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&g_init_mu); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int grpc_is_initialized(void) { |
|
|
|
|
int r; |
|
|
|
|
gpr_once_init(&g_basic_init, do_basic_init); |
|
|
|
|
gpr_mu_lock(&g_init_mu); |
|
|
|
|
grpc_core::MutexLock lock(&g_init_mu); |
|
|
|
|
r = g_initializations > 0; |
|
|
|
|
gpr_mu_unlock(&g_init_mu); |
|
|
|
|
return r; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void grpc_maybe_wait_for_async_shutdown(void) { |
|
|
|
|
gpr_once_init(&g_basic_init, do_basic_init); |
|
|
|
|
grpc_core::MutexLock lock(&g_init_mu); |
|
|
|
|
while (g_shutting_down) { |
|
|
|
|
gpr_cv_wait(g_shutting_down_cv, &g_init_mu, |
|
|
|
|
gpr_inf_future(GPR_CLOCK_REALTIME)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|