• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include <grpc/support/port_platform.h>
20 
21 #include <limits.h>
22 #include <memory.h>
23 
24 #include <grpc/fork.h>
25 #include <grpc/grpc.h>
26 #include <grpc/support/alloc.h>
27 #include <grpc/support/log.h>
28 #include <grpc/support/time.h>
29 #include "src/core/lib/channel/channel_stack.h"
30 #include "src/core/lib/channel/channelz_registry.h"
31 #include "src/core/lib/channel/connected_channel.h"
32 #include "src/core/lib/channel/handshaker_registry.h"
33 #include "src/core/lib/debug/stats.h"
34 #include "src/core/lib/debug/trace.h"
35 #include "src/core/lib/gprpp/fork.h"
36 #include "src/core/lib/gprpp/sync.h"
37 #include "src/core/lib/http/parser.h"
38 #include "src/core/lib/iomgr/call_combiner.h"
39 #include "src/core/lib/iomgr/combiner.h"
40 #include "src/core/lib/iomgr/executor.h"
41 #include "src/core/lib/iomgr/iomgr.h"
42 #include "src/core/lib/iomgr/resource_quota.h"
43 #include "src/core/lib/iomgr/timer_manager.h"
44 #include "src/core/lib/profiling/timers.h"
45 #include "src/core/lib/slice/slice_internal.h"
46 #include "src/core/lib/surface/api_trace.h"
47 #include "src/core/lib/surface/call.h"
48 #include "src/core/lib/surface/channel_init.h"
49 #include "src/core/lib/surface/completion_queue.h"
50 #include "src/core/lib/surface/init.h"
51 #include "src/core/lib/surface/lame_client.h"
52 #include "src/core/lib/surface/server.h"
53 #include "src/core/lib/transport/bdp_estimator.h"
54 #include "src/core/lib/transport/connectivity_state.h"
55 #include "src/core/lib/transport/transport_impl.h"
56 
57 /* (generated) built in registry of plugins */
58 extern void grpc_register_built_in_plugins(void);
59 
60 #define MAX_PLUGINS 128
61 
62 static gpr_once g_basic_init = GPR_ONCE_INIT;
63 static gpr_mu g_init_mu;
64 static int g_initializations;
65 static gpr_cv* g_shutting_down_cv;
66 static bool g_shutting_down;
67 
do_basic_init(void)68 static void do_basic_init(void) {
69   gpr_log_verbosity_init();
70   gpr_mu_init(&g_init_mu);
71   g_shutting_down_cv = static_cast<gpr_cv*>(malloc(sizeof(gpr_cv)));
72   gpr_cv_init(g_shutting_down_cv);
73   g_shutting_down = false;
74   grpc_register_built_in_plugins();
75   grpc_cq_global_init();
76   grpc_core::grpc_executor_global_init();
77   gpr_time_init();
78   g_initializations = 0;
79 }
80 
append_filter(grpc_channel_stack_builder * builder,void * arg)81 static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
82   return grpc_channel_stack_builder_append_filter(
83       builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
84 }
85 
prepend_filter(grpc_channel_stack_builder * builder,void * arg)86 static bool prepend_filter(grpc_channel_stack_builder* builder, void* arg) {
87   return grpc_channel_stack_builder_prepend_filter(
88       builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
89 }
90 
register_builtin_channel_init()91 static void register_builtin_channel_init() {
92   grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
93                                    GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
94                                    grpc_add_connected_filter, nullptr);
95   grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
96                                    GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
97                                    grpc_add_connected_filter, nullptr);
98   grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
99                                    GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
100                                    grpc_add_connected_filter, nullptr);
101   grpc_channel_init_register_stage(GRPC_CLIENT_LAME_CHANNEL,
102                                    GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
103                                    append_filter, (void*)&grpc_lame_filter);
104   grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX, prepend_filter,
105                                    (void*)&grpc_server_top_filter);
106 }
107 
108 typedef struct grpc_plugin {
109   void (*init)();
110   void (*destroy)();
111 } grpc_plugin;
112 
113 static grpc_plugin g_all_of_the_plugins[MAX_PLUGINS];
114 static int g_number_of_plugins = 0;
115 
grpc_register_plugin(void (* init)(void),void (* destroy)(void))116 void grpc_register_plugin(void (*init)(void), void (*destroy)(void)) {
117   GRPC_API_TRACE("grpc_register_plugin(init=%p, destroy=%p)", 2,
118                  ((void*)(intptr_t)init, (void*)(intptr_t)destroy));
119   GPR_ASSERT(g_number_of_plugins != MAX_PLUGINS);
120   g_all_of_the_plugins[g_number_of_plugins].init = init;
121   g_all_of_the_plugins[g_number_of_plugins].destroy = destroy;
122   g_number_of_plugins++;
123 }
124 
grpc_init(void)125 void grpc_init(void) {
126   int i;
127   gpr_once_init(&g_basic_init, do_basic_init);
128 
129   grpc_core::MutexLock lock(&g_init_mu);
130   if (++g_initializations == 1) {
131     if (g_shutting_down) {
132       g_shutting_down = false;
133       gpr_cv_broadcast(g_shutting_down_cv);
134     }
135     grpc_core::Fork::GlobalInit();
136     grpc_fork_handlers_auto_register();
137     grpc_stats_init();
138     grpc_init_static_metadata_ctx();
139     grpc_slice_intern_init();
140     grpc_mdctx_global_init();
141     grpc_channel_init_init();
142     grpc_core::channelz::ChannelzRegistry::Init();
143     grpc_security_pre_init();
144     grpc_core::ApplicationCallbackExecCtx::GlobalInit();
145     grpc_core::ExecCtx::GlobalInit();
146     grpc_iomgr_init();
147     grpc_cq_init();
148     gpr_timers_global_init();
149     grpc_core::HandshakerRegistry::Init();
150     grpc_security_init();
151     for (i = 0; i < g_number_of_plugins; i++) {
152       if (g_all_of_the_plugins[i].init != nullptr) {
153         g_all_of_the_plugins[i].init();
154       }
155     }
156     /* register channel finalization AFTER all plugins, to ensure that it's run
157      * at the appropriate time */
158     grpc_register_security_filters();
159     register_builtin_channel_init();
160     grpc_tracer_init();
161     /* no more changes to channel init pipelines */
162     grpc_channel_init_finalize();
163     grpc_iomgr_start();
164   }
165 
166   GRPC_API_TRACE("grpc_init(void)", 0, ());
167 }
168 
grpc_shutdown_internal_locked(void)169 void grpc_shutdown_internal_locked(void) {
170   int i;
171   {
172     grpc_core::ExecCtx exec_ctx(0);
173     grpc_cq_shutdown();
174     grpc_iomgr_shutdown_background_closure();
175     {
176       grpc_timer_manager_set_threading(false);  // shutdown timer_manager thread
177       grpc_core::Executor::ShutdownAll();
178       for (i = g_number_of_plugins; i >= 0; i--) {
179         if (g_all_of_the_plugins[i].destroy != nullptr) {
180           g_all_of_the_plugins[i].destroy();
181         }
182       }
183     }
184     grpc_iomgr_shutdown();
185     gpr_timers_global_destroy();
186     grpc_tracer_shutdown();
187     grpc_mdctx_global_shutdown();
188     grpc_core::HandshakerRegistry::Shutdown();
189     grpc_slice_intern_shutdown();
190     grpc_core::channelz::ChannelzRegistry::Shutdown();
191     grpc_stats_shutdown();
192     grpc_core::Fork::GlobalShutdown();
193   }
194   grpc_core::ExecCtx::GlobalShutdown();
195   grpc_core::ApplicationCallbackExecCtx::GlobalShutdown();
196   g_shutting_down = false;
197   gpr_cv_broadcast(g_shutting_down_cv);
198   // Absolute last action will be to delete static metadata context.
199   grpc_destroy_static_metadata_ctx();
200 }
201 
grpc_shutdown_internal(void *)202 void grpc_shutdown_internal(void* /*ignored*/) {
203   GRPC_API_TRACE("grpc_shutdown_internal", 0, ());
204   grpc_core::MutexLock lock(&g_init_mu);
205   // We have released lock from the shutdown thread and it is possible that
206   // another grpc_init has been called, and do nothing if that is the case.
207   if (--g_initializations != 0) {
208     return;
209   }
210   grpc_shutdown_internal_locked();
211 }
212 
grpc_shutdown(void)213 void grpc_shutdown(void) {
214   GRPC_API_TRACE("grpc_shutdown(void)", 0, ());
215   grpc_core::MutexLock lock(&g_init_mu);
216   if (--g_initializations == 0) {
217     g_initializations++;
218     g_shutting_down = true;
219     // spawn a detached thread to do the actual clean up in case we are
220     // currently in an executor thread.
221     grpc_core::Thread cleanup_thread(
222         "grpc_shutdown", grpc_shutdown_internal, nullptr, nullptr,
223         grpc_core::Thread::Options().set_joinable(false).set_tracked(false));
224     cleanup_thread.Start();
225   }
226 }
227 
grpc_shutdown_blocking(void)228 void grpc_shutdown_blocking(void) {
229   GRPC_API_TRACE("grpc_shutdown_blocking(void)", 0, ());
230   grpc_core::MutexLock lock(&g_init_mu);
231   if (--g_initializations == 0) {
232     g_shutting_down = true;
233     grpc_shutdown_internal_locked();
234   }
235 }
236 
grpc_is_initialized(void)237 int grpc_is_initialized(void) {
238   int r;
239   gpr_once_init(&g_basic_init, do_basic_init);
240   grpc_core::MutexLock lock(&g_init_mu);
241   r = g_initializations > 0;
242   return r;
243 }
244 
grpc_maybe_wait_for_async_shutdown(void)245 void grpc_maybe_wait_for_async_shutdown(void) {
246   gpr_once_init(&g_basic_init, do_basic_init);
247   grpc_core::MutexLock lock(&g_init_mu);
248   while (g_shutting_down) {
249     gpr_cv_wait(g_shutting_down_cv, &g_init_mu,
250                 gpr_inf_future(GPR_CLOCK_REALTIME));
251   }
252 }
253