blob: 3ab4430668e1ab86c6439d1986b1dcf12a02989a [file] [log] [blame]
ctiller58393c22015-01-07 14:03:30 -08001/*
2 *
Craig Tillerf315bc12016-02-18 08:25:15 -08003 * Copyright 2015-2016, Google Inc.
ctiller58393c22015-01-07 14:03:30 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "src/core/iomgr/iomgr.h"
35
36#include <stdlib.h>
Craig Tiller131f6ed2015-09-15 08:20:20 -070037#include <string.h>
ctiller58393c22015-01-07 14:03:30 -080038
ctiller58393c22015-01-07 14:03:30 -080039#include <grpc/support/alloc.h>
40#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070041#include <grpc/support/string_util.h>
ctiller58393c22015-01-07 14:03:30 -080042#include <grpc/support/sync.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070043#include <grpc/support/thd.h>
Craig Tiller0cb803d2016-03-02 22:17:24 -080044#include <grpc/support/useful.h>
ctiller58393c22015-01-07 14:03:30 -080045
Craig Tilleref1bf872016-02-28 17:37:33 -080046#include "src/core/iomgr/exec_ctx.h"
Craig Tiller131f6ed2015-09-15 08:20:20 -070047#include "src/core/iomgr/iomgr_internal.h"
Craig Tillerccdea192016-02-16 08:06:46 -080048#include "src/core/iomgr/timer.h"
Craig Tiller0cb803d2016-03-02 22:17:24 -080049#include "src/core/support/env.h"
Craig Tiller131f6ed2015-09-15 08:20:20 -070050#include "src/core/support/string.h"
51
ctiller58393c22015-01-07 14:03:30 -080052static gpr_mu g_mu;
Nicolas "Pixel" Nobleae7b45a2015-02-04 03:28:34 +010053static gpr_cv g_rcv;
ctiller58393c22015-01-07 14:03:30 -080054static int g_shutdown;
Craig Tillerfa275a92015-06-01 13:55:54 -070055static grpc_iomgr_object g_root_object;
ctiller58393c22015-01-07 14:03:30 -080056
Craig Tillera82950e2015-09-22 12:33:20 -070057void grpc_iomgr_init(void) {
Craig Tiller994c2622015-07-23 14:00:58 -070058 g_shutdown = 0;
Craig Tillera82950e2015-09-22 12:33:20 -070059 gpr_mu_init(&g_mu);
60 gpr_cv_init(&g_rcv);
Craig Tilleref1bf872016-02-28 17:37:33 -080061 grpc_exec_ctx_global_init();
David Garcia Quintasf747bbc2015-10-04 23:09:47 -070062 grpc_timer_list_init(gpr_now(GPR_CLOCK_MONOTONIC));
Craig Tillerfa275a92015-06-01 13:55:54 -070063 g_root_object.next = g_root_object.prev = &g_root_object;
64 g_root_object.name = "root";
Craig Tillera82950e2015-09-22 12:33:20 -070065 grpc_iomgr_platform_init();
Craig Tiller3dedb702015-09-24 10:31:26 -070066 grpc_pollset_global_init();
ctiller58393c22015-01-07 14:03:30 -080067}
68
Craig Tillera82950e2015-09-22 12:33:20 -070069static size_t count_objects(void) {
Craig Tillerfa275a92015-06-01 13:55:54 -070070 grpc_iomgr_object *obj;
71 size_t n = 0;
Craig Tillera82950e2015-09-22 12:33:20 -070072 for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {
73 n++;
74 }
Craig Tillerfa275a92015-06-01 13:55:54 -070075 return n;
76}
77
Craig Tillera82950e2015-09-22 12:33:20 -070078static void dump_objects(const char *kind) {
Craig Tillerfa275a92015-06-01 13:55:54 -070079 grpc_iomgr_object *obj;
Craig Tillera82950e2015-09-22 12:33:20 -070080 for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) {
81 gpr_log(GPR_DEBUG, "%s OBJECT: %s %p", kind, obj->name, obj);
82 }
Craig Tiller49d03c82015-09-03 14:34:30 -070083}
84
Craig Tillera82950e2015-09-22 12:33:20 -070085void grpc_iomgr_shutdown(void) {
86 gpr_timespec shutdown_deadline = gpr_time_add(
87 gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN));
88 gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
Craig Tillerf5768a62015-09-22 10:54:34 -070089 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
ctiller58393c22015-01-07 14:03:30 -080090
Craig Tiller01be53d2015-09-30 08:36:03 -070091 grpc_iomgr_platform_flush();
92
Craig Tillera82950e2015-09-22 12:33:20 -070093 gpr_mu_lock(&g_mu);
ctiller58393c22015-01-07 14:03:30 -080094 g_shutdown = 1;
Craig Tillera82950e2015-09-22 12:33:20 -070095 while (g_root_object.next != &g_root_object) {
96 if (gpr_time_cmp(
97 gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time),
98 gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
99 if (g_root_object.next != &g_root_object) {
100 gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed",
101 count_objects());
102 }
103 last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
Craig Tiller29f741f2015-05-29 12:29:43 -0700104 }
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700105 if (grpc_timer_check(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC),
Craig Tillera82950e2015-09-22 12:33:20 -0700106 NULL)) {
107 gpr_mu_unlock(&g_mu);
Craig Tiller63010382015-09-24 15:00:58 -0700108 grpc_exec_ctx_flush(&exec_ctx);
Craig Tillera82950e2015-09-22 12:33:20 -0700109 gpr_mu_lock(&g_mu);
110 continue;
111 }
112 if (g_root_object.next != &g_root_object) {
Craig Tillera82950e2015-09-22 12:33:20 -0700113 gpr_timespec short_deadline = gpr_time_add(
114 gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN));
115 if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline)) {
116 if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) {
Craig Tiller63010382015-09-24 15:00:58 -0700117 if (g_root_object.next != &g_root_object) {
118 gpr_log(GPR_DEBUG,
119 "Failed to free %d iomgr objects before shutdown deadline: "
120 "memory leaks are likely",
121 count_objects());
122 dump_objects("LEAKED");
Craig Tiller0cb803d2016-03-02 22:17:24 -0800123 if (grpc_iomgr_abort_on_leaks()) {
124 abort();
125 }
Craig Tiller63010382015-09-24 15:00:58 -0700126 }
Craig Tillera82950e2015-09-22 12:33:20 -0700127 break;
128 }
129 }
Craig Tillera82950e2015-09-22 12:33:20 -0700130 }
131 }
132 gpr_mu_unlock(&g_mu);
ctiller58393c22015-01-07 14:03:30 -0800133
David Garcia Quintasf747bbc2015-10-04 23:09:47 -0700134 grpc_timer_list_shutdown(&exec_ctx);
Craig Tillera82950e2015-09-22 12:33:20 -0700135 grpc_exec_ctx_finish(&exec_ctx);
Craig Tiller8e0b08a2015-06-01 17:04:17 -0700136
Craig Tiller62aef622015-09-21 21:27:54 -0700137 /* ensure all threads have left g_mu */
Craig Tillera82950e2015-09-22 12:33:20 -0700138 gpr_mu_lock(&g_mu);
139 gpr_mu_unlock(&g_mu);
Craig Tiller62aef622015-09-21 21:27:54 -0700140
Craig Tiller3dedb702015-09-24 10:31:26 -0700141 grpc_pollset_global_shutdown();
Craig Tillera82950e2015-09-22 12:33:20 -0700142 grpc_iomgr_platform_shutdown();
Craig Tilleref1bf872016-02-28 17:37:33 -0800143 grpc_exec_ctx_global_shutdown();
Craig Tillera82950e2015-09-22 12:33:20 -0700144 gpr_mu_destroy(&g_mu);
145 gpr_cv_destroy(&g_rcv);
ctiller58393c22015-01-07 14:03:30 -0800146}
147
Craig Tillera82950e2015-09-22 12:33:20 -0700148void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name) {
149 obj->name = gpr_strdup(name);
150 gpr_mu_lock(&g_mu);
Craig Tillerfa275a92015-06-01 13:55:54 -0700151 obj->next = &g_root_object;
Craig Tiller49d03c82015-09-03 14:34:30 -0700152 obj->prev = g_root_object.prev;
Craig Tillerfa275a92015-06-01 13:55:54 -0700153 obj->next->prev = obj->prev->next = obj;
Craig Tillera82950e2015-09-22 12:33:20 -0700154 gpr_mu_unlock(&g_mu);
ctiller58393c22015-01-07 14:03:30 -0800155}
156
Craig Tillera82950e2015-09-22 12:33:20 -0700157void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) {
158 gpr_mu_lock(&g_mu);
Craig Tillerfa275a92015-06-01 13:55:54 -0700159 obj->next->prev = obj->prev;
160 obj->prev->next = obj->next;
Craig Tillera82950e2015-09-22 12:33:20 -0700161 gpr_cv_signal(&g_rcv);
162 gpr_mu_unlock(&g_mu);
163 gpr_free(obj->name);
ctiller58393c22015-01-07 14:03:30 -0800164}
Craig Tiller0cb803d2016-03-02 22:17:24 -0800165
166bool grpc_iomgr_abort_on_leaks(void) {
167 char *env = gpr_getenv("GRPC_ABORT_ON_LEAKS");
168 if (env == NULL) return false;
169 static const char *truthy[] = {"yes", "Yes", "YES", "true",
170 "True", "TRUE", "1"};
171 for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
172 if (0 == strcmp(env, truthy[i])) return true;
173 }
174 return false;
175}