aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Vijay Pai <vpai@google.com>2018-02-16 19:37:16 -0800
committerGravatar Vijay Pai <vpai@google.com>2018-02-16 19:51:36 -0800
commit5e1298f0a826777b0e5b844328b81216e9c37476 (patch)
tree5e09ef74976851e20459d7fbd5c69c8f1ca8e195
parent58a62755fc6546a117b7b8f3a0a344f85b2ea5f9 (diff)
Fix thread leak by delaying thread exit until join is ready
-rw-r--r--src/core/lib/iomgr/ev_poll_posix.cc20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/core/lib/iomgr/ev_poll_posix.cc b/src/core/lib/iomgr/ev_poll_posix.cc
index 404665c11f..0d1e67dfdf 100644
--- a/src/core/lib/iomgr/ev_poll_posix.cc
+++ b/src/core/lib/iomgr/ev_poll_posix.cc
@@ -256,6 +256,8 @@ typedef struct poll_args {
gpr_thd_id poller_thd;
gpr_cv trigger;
int trigger_set;
+ gpr_cv harvest;
+ gpr_cv join;
struct pollfd* fds;
nfds_t nfds;
poll_result* result;
@@ -263,11 +265,6 @@ typedef struct poll_args {
struct poll_args* prev;
} poll_args;
-typedef struct poller_dead {
- gpr_thd_id poller_thd;
- struct poller_dead* next;
-} poller_dead;
-
// This is a 2-tiered cache, we mantain a hash table
// of active poll calls, so we can wait on the result
// of that call. We also maintain freelists of inactive
@@ -280,6 +277,7 @@ typedef struct poll_hash_table {
unsigned int count;
} poll_hash_table;
+// TODO(kpayson64): Eliminate use of global non-POD variables
poll_hash_table poll_cache;
grpc_cv_fd_table g_cvfds;
@@ -1369,6 +1367,8 @@ static poll_args* get_poller_locked(struct pollfd* fds, nfds_t count) {
poll_args* pargs =
static_cast<poll_args*>(gpr_malloc(sizeof(struct poll_args)));
gpr_cv_init(&pargs->trigger);
+ gpr_cv_init(&pargs->harvest);
+ gpr_cv_init(&pargs->join);
pargs->fds = fds;
pargs->nfds = count;
pargs->next = nullptr;
@@ -1455,6 +1455,13 @@ static void cache_harvest_locked() {
while (poll_cache.dead_pollers) {
poll_args* args = poll_cache.dead_pollers;
poll_cache.dead_pollers = poll_cache.dead_pollers->next;
+ // Keep the list consistent in case new dead pollers get added when we
+ // release the lock below to wait on joining
+ if (poll_cache.dead_pollers) {
+ poll_cache.dead_pollers->prev = nullptr;
+ }
+ gpr_cv_signal(&args->harvest);
+ gpr_cv_wait(&args->join, &g_cvfds.mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
gpr_thd_join(args->poller_thd);
gpr_free(args);
}
@@ -1521,6 +1528,9 @@ static void run_poll(void* args) {
if (gpr_unref(&g_cvfds.pollcount)) {
gpr_cv_signal(&g_cvfds.shutdown_cv);
}
+ gpr_cv_wait(&pargs->harvest, &g_cvfds.mu,
+ gpr_inf_future(GPR_CLOCK_MONOTONIC));
+ gpr_cv_signal(&pargs->join);
gpr_mu_unlock(&g_cvfds.mu);
}