Merge pull request #13655 from yang-g/ping

Bug fix, use the last_sent ping time for next send
diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h
index 1906886..5a0ed85 100644
--- a/include/grpc/impl/codegen/port_platform.h
+++ b/include/grpc/impl/codegen/port_platform.h
@@ -173,6 +173,7 @@
 #endif /* _LP64 */
 #ifdef __GLIBC__
 #define GPR_POSIX_CRASH_HANDLER 1
+#define GPR_LINUX_PTHREAD_NAME 1
 #else /* musl libc */
 #define GPR_MUSL_LIBC_COMPAT 1
 #endif
@@ -195,6 +196,7 @@
 #else /* __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 */
 #define GPR_CPU_POSIX 1
 #define GPR_GCC_TLS 1
+#define GPR_APPLE_PTHREAD_NAME 1
 #endif
 #else /* __MAC_OS_X_VERSION_MIN_REQUIRED */
 #define GPR_CPU_POSIX 1
diff --git a/include/grpc/support/thd.h b/include/grpc/support/thd.h
index 225d9d6..e9444e8 100644
--- a/include/grpc/support/thd.h
+++ b/include/grpc/support/thd.h
@@ -42,9 +42,12 @@
 
 /** Create a new thread running (*thd_body)(arg) and place its thread identifier
    in *t, and return true.  If there are insufficient resources, return false.
+   thd_name is the name of the thread for identification purposes on platforms
+   that support thread naming.
    If options==NULL, default options are used.
    The thread is immediately runnable, and exits when (*thd_body)() returns.  */
-GPRAPI int gpr_thd_new(gpr_thd_id* t, void (*thd_body)(void* arg), void* arg,
+GPRAPI int gpr_thd_new(gpr_thd_id* t, const char* thd_name,
+                       void (*thd_body)(void* arg), void* arg,
                        const gpr_thd_options* options);
 
 /** Return a gpr_thd_options struct with all fields set to defaults. */
diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
index f68daba..31a26bc 100644
--- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
@@ -365,19 +365,18 @@
    *    CHECK: subchannel_list->num_shutdown ==
    *           subchannel_list->num_subchannels.
    *
-   * 4) RULE: ALL subchannels are TRANSIENT_FAILURE => policy is
+   * 4) RULE: ALL subchannels are SHUTDOWN or TRANSIENT_FAILURE => policy is
    *          TRANSIENT_FAILURE.
-   *    CHECK: subchannel_list->num_transient_failures ==
-   *           subchannel_list->num_subchannels.
+   *    CHECK: subchannel_list->num_shutdown +
+                 subchannel_list->num_transient_failures ==
+               subchannel_list->num_subchannels.
    *
    * 5) RULE: ALL subchannels are IDLE => policy is IDLE.
    *    CHECK: subchannel_list->num_idle == subchannel_list->num_subchannels.
    *    (Note that all the subchannels will transition from IDLE to CONNECTING
    *    in batch when we start trying to connect.)
    */
-  // TODO(juanlishen): if the subchannel states are mixed by {SHUTDOWN,
-  // TRANSIENT_FAILURE}, we don't change the state. We may want to improve on
-  // this.
+  // TODO(juanlishen): For rule 4, we may want to re-resolve instead.
   grpc_lb_subchannel_list* subchannel_list = sd->subchannel_list;
   round_robin_lb_policy* p = (round_robin_lb_policy*)subchannel_list->policy;
   if (subchannel_list->num_ready > 0) {
@@ -398,7 +397,8 @@
     p->started_picking = false;
     grpc_lb_policy_try_reresolve(exec_ctx, &p->base, &grpc_lb_round_robin_trace,
                                  GRPC_ERROR_NONE);
-  } else if (subchannel_list->num_transient_failures ==
+  } else if (subchannel_list->num_shutdown +
+                 subchannel_list->num_transient_failures ==
              subchannel_list->num_subchannels) {
     /* 4) TRANSIENT_FAILURE */
     grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc
index 4d24efe..8836a32 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.cc
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc
@@ -401,7 +401,7 @@
   Cronet callback
 */
 static void on_failed(bidirectional_stream* stream, int net_error) {
-  CRONET_LOG(GPR_DEBUG, "on_failed(%p, %d)", stream, net_error);
+  gpr_log(GPR_ERROR, "on_failed(%p, %d)", stream, net_error);
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
 
   stream_obj* s = (stream_obj*)stream->annotation;
diff --git a/src/core/lib/iomgr/ev_poll_posix.cc b/src/core/lib/iomgr/ev_poll_posix.cc
index 8659559..e32e1ba 100644
--- a/src/core/lib/iomgr/ev_poll_posix.cc
+++ b/src/core/lib/iomgr/ev_poll_posix.cc
@@ -1382,7 +1382,7 @@
   gpr_thd_options opt = gpr_thd_options_default();
   gpr_ref(&g_cvfds.pollcount);
   gpr_thd_options_set_detached(&opt);
-  GPR_ASSERT(gpr_thd_new(&t_id, &run_poll, pargs, &opt));
+  GPR_ASSERT(gpr_thd_new(&t_id, "grpc_poller", &run_poll, pargs, &opt));
   return pargs;
 }
 
diff --git a/src/core/lib/iomgr/executor.cc b/src/core/lib/iomgr/executor.cc
index d8a195f..fabdbdf 100644
--- a/src/core/lib/iomgr/executor.cc
+++ b/src/core/lib/iomgr/executor.cc
@@ -104,8 +104,8 @@
 
     gpr_thd_options opt = gpr_thd_options_default();
     gpr_thd_options_set_joinable(&opt);
-    gpr_thd_new(&g_thread_state[0].id, executor_thread, &g_thread_state[0],
-                &opt);
+    gpr_thd_new(&g_thread_state[0].id, "grpc_executor", executor_thread,
+                &g_thread_state[0], &opt);
   } else {
     if (cur_threads == 0) return;
     for (size_t i = 0; i < g_max_threads; i++) {
@@ -263,8 +263,8 @@
 
         gpr_thd_options opt = gpr_thd_options_default();
         gpr_thd_options_set_joinable(&opt);
-        gpr_thd_new(&g_thread_state[cur_thread_count].id, executor_thread,
-                    &g_thread_state[cur_thread_count], &opt);
+        gpr_thd_new(&g_thread_state[cur_thread_count].id, "gpr_executor",
+                    executor_thread, &g_thread_state[cur_thread_count], &opt);
       }
       gpr_spinlock_unlock(&g_adding_thread_lock);
     }
diff --git a/src/core/lib/iomgr/timer_manager.cc b/src/core/lib/iomgr/timer_manager.cc
index dac74ae..87ed0e0 100644
--- a/src/core/lib/iomgr/timer_manager.cc
+++ b/src/core/lib/iomgr/timer_manager.cc
@@ -93,7 +93,7 @@
   // to leak through g_completed_threads and be freed in gc_completed_threads()
   // before "&ct->t" is written to, causing a use-after-free.
   gpr_mu_lock(&g_mu);
-  gpr_thd_new(&ct->t, timer_thread, ct, &opt);
+  gpr_thd_new(&ct->t, "grpc_global_timer", timer_thread, ct, &opt);
   gpr_mu_unlock(&g_mu);
 }
 
diff --git a/src/core/lib/profiling/basic_timers.cc b/src/core/lib/profiling/basic_timers.cc
index 3ec6280..87dd4ab 100644
--- a/src/core/lib/profiling/basic_timers.cc
+++ b/src/core/lib/profiling/basic_timers.cc
@@ -203,7 +203,8 @@
 static void init_output() {
   gpr_thd_options options = gpr_thd_options_default();
   gpr_thd_options_set_joinable(&options);
-  GPR_ASSERT(gpr_thd_new(&g_writing_thread, writing_thread, NULL, &options));
+  GPR_ASSERT(gpr_thd_new(&g_writing_thread, "timer_output_thread",
+                         writing_thread, NULL, &options));
   atexit(finish_writing);
 }
 
diff --git a/src/core/lib/support/thd_posix.cc b/src/core/lib/support/thd_posix.cc
index c2a4f41..f0ed48d 100644
--- a/src/core/lib/support/thd_posix.cc
+++ b/src/core/lib/support/thd_posix.cc
@@ -41,6 +41,7 @@
 struct thd_arg {
   void (*body)(void* arg); /* body of a thread */
   void* arg;               /* argument to a thread */
+  const char* name;        /* name of thread. Can be nullptr. */
 };
 
 static void inc_thd_count();
@@ -50,12 +51,26 @@
 static void* thread_body(void* v) {
   struct thd_arg a = *(struct thd_arg*)v;
   free(v);
+  if (a.name != nullptr) {
+#if GPR_APPLE_PTHREAD_NAME
+    /* Apple supports 64 characters, and will truncate if it's longer. */
+    pthread_setname_np(a.name);
+#elif GPR_LINUX_PTHREAD_NAME
+    /* Linux supports 16 characters max, and will error if it's longer. */
+    char buf[16];
+    size_t buf_len = GPR_ARRAY_SIZE(buf) - 1;
+    strncpy(buf, a.name, buf_len);
+    buf[buf_len] = '\0';
+    pthread_setname_np(pthread_self(), buf);
+#endif  // GPR_APPLE_PTHREAD_NAME
+  }
   (*a.body)(a.arg);
   dec_thd_count();
   return nullptr;
 }
 
-int gpr_thd_new(gpr_thd_id* t, void (*thd_body)(void* arg), void* arg,
+int gpr_thd_new(gpr_thd_id* t, const char* thd_name,
+                void (*thd_body)(void* arg), void* arg,
                 const gpr_thd_options* options) {
   int thread_started;
   pthread_attr_t attr;
@@ -66,6 +81,7 @@
   GPR_ASSERT(a != nullptr);
   a->body = thd_body;
   a->arg = arg;
+  a->name = thd_name;
   inc_thd_count();
 
   GPR_ASSERT(pthread_attr_init(&attr) == 0);
diff --git a/src/core/lib/support/thd_windows.cc b/src/core/lib/support/thd_windows.cc
index 0875c2f..f920770 100644
--- a/src/core/lib/support/thd_windows.cc
+++ b/src/core/lib/support/thd_windows.cc
@@ -65,7 +65,8 @@
   return 0;
 }
 
-int gpr_thd_new(gpr_thd_id* t, void (*thd_body)(void* arg), void* arg,
+int gpr_thd_new(gpr_thd_id* t, const char* thd_name,
+                void (*thd_body)(void* arg), void* arg,
                 const gpr_thd_options* options) {
   HANDLE handle;
   struct thd_info* info = (struct thd_info*)gpr_malloc(sizeof(*info));
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 62223fd..fae7784 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -768,7 +768,7 @@
 typedef intptr_t(*gpr_stats_read_type)(const gpr_stats_counter* c);
 extern gpr_stats_read_type gpr_stats_read_import;
 #define gpr_stats_read gpr_stats_read_import
-typedef int(*gpr_thd_new_type)(gpr_thd_id* t, void (*thd_body)(void* arg), void* arg, const gpr_thd_options* options);
+typedef int(*gpr_thd_new_type)(gpr_thd_id* t, const char* thd_name, void (*thd_body)(void* arg), void* arg, const gpr_thd_options* options);
 extern gpr_thd_new_type gpr_thd_new_import;
 #define gpr_thd_new gpr_thd_new_import
 typedef gpr_thd_options(*gpr_thd_options_default_type)(void);
diff --git a/test/core/bad_client/bad_client.cc b/test/core/bad_client/bad_client.cc
index 0a7b1c7..d8bb092 100644
--- a/test/core/bad_client/bad_client.cc
+++ b/test/core/bad_client/bad_client.cc
@@ -129,7 +129,7 @@
   GPR_ASSERT(grpc_server_has_open_connections(a.server));
 
   /* Start validator */
-  gpr_thd_new(&id, thd_func, &a, nullptr);
+  gpr_thd_new(&id, "grpc_bad_client", thd_func, &a, nullptr);
 
   grpc_slice_buffer_init(&outgoing);
   grpc_slice_buffer_add(&outgoing, slice);
diff --git a/test/core/end2end/bad_server_response_test.cc b/test/core/end2end/bad_server_response_test.cc
index b0c6ae9..0fdb637 100644
--- a/test/core/end2end/bad_server_response_test.cc
+++ b/test/core/end2end/bad_server_response_test.cc
@@ -262,7 +262,7 @@
   poll_args* pa = (poll_args*)gpr_malloc(sizeof(*pa));
   pa->server = server;
   pa->signal_when_done = signal_when_done;
-  gpr_thd_new(&id, actually_poll_server, pa, nullptr);
+  gpr_thd_new(&id, "grpc_poll_server", actually_poll_server, pa, nullptr);
 }
 
 static void run_test(const char* response_payload,
diff --git a/test/core/end2end/fixtures/http_proxy_fixture.cc b/test/core/end2end/fixtures/http_proxy_fixture.cc
index 0cec27b..3904887 100644
--- a/test/core/end2end/fixtures/http_proxy_fixture.cc
+++ b/test/core/end2end/fixtures/http_proxy_fixture.cc
@@ -574,7 +574,8 @@
   // Start proxy thread.
   gpr_thd_options opt = gpr_thd_options_default();
   gpr_thd_options_set_joinable(&opt);
-  GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt));
+  GPR_ASSERT(
+      gpr_thd_new(&proxy->thd, "grpc_http_proxy", thread_main, proxy, &opt));
   return proxy;
 }
 
diff --git a/test/core/end2end/fixtures/proxy.cc b/test/core/end2end/fixtures/proxy.cc
index 2fab62b..b1698c8 100644
--- a/test/core/end2end/fixtures/proxy.cc
+++ b/test/core/end2end/fixtures/proxy.cc
@@ -98,7 +98,8 @@
 
   grpc_call_details_init(&proxy->new_call_details);
   gpr_thd_options_set_joinable(&opt);
-  GPR_ASSERT(gpr_thd_new(&proxy->thd, thread_main, proxy, &opt));
+  GPR_ASSERT(
+      gpr_thd_new(&proxy->thd, "grpc_end2end_proxy", thread_main, proxy, &opt));
 
   request_call(proxy);
 
diff --git a/test/core/end2end/tests/connectivity.cc b/test/core/end2end/tests/connectivity.cc
index 2ea4ca8..da65080 100644
--- a/test/core/end2end/tests/connectivity.cc
+++ b/test/core/end2end/tests/connectivity.cc
@@ -68,7 +68,8 @@
   ce.cq = f.cq;
   gpr_event_init(&ce.started);
   gpr_thd_options_set_joinable(&thdopt);
-  GPR_ASSERT(gpr_thd_new(&thdid, child_thread, &ce, &thdopt));
+  GPR_ASSERT(
+      gpr_thd_new(&thdid, "grpc_connectivity", child_thread, &ce, &thdopt));
 
   gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC));
 
diff --git a/test/core/handshake/client_ssl.cc b/test/core/handshake/client_ssl.cc
index 2b149a7..2302e3d 100644
--- a/test/core/handshake/client_ssl.cc
+++ b/test/core/handshake/client_ssl.cc
@@ -231,7 +231,8 @@
   gpr_thd_id thdid;
   gpr_thd_options_set_joinable(&thdopt);
   server_args args = {server_socket, server_alpn_preferred};
-  GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &args, &thdopt));
+  GPR_ASSERT(gpr_thd_new(&thdid, "grpc_client_ssl_test", server_thread, &args,
+                         &thdopt));
 
   // Load key pair and establish client SSL credentials.
   grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
diff --git a/test/core/handshake/server_ssl_common.cc b/test/core/handshake/server_ssl_common.cc
index 599b281..0bf453a 100644
--- a/test/core/handshake/server_ssl_common.cc
+++ b/test/core/handshake/server_ssl_common.cc
@@ -137,7 +137,8 @@
   gpr_thd_options thdopt = gpr_thd_options_default();
   gpr_thd_id thdid;
   gpr_thd_options_set_joinable(&thdopt);
-  GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt));
+  GPR_ASSERT(
+      gpr_thd_new(&thdid, "grpc_ssl_test", server_thread, &port, &thdopt));
 
   SSL_load_error_strings();
   OpenSSL_add_ssl_algorithms();
diff --git a/test/core/iomgr/combiner_test.cc b/test/core/iomgr/combiner_test.cc
index 146a6bd..33d892f 100644
--- a/test/core/iomgr/combiner_test.cc
+++ b/test/core/iomgr/combiner_test.cc
@@ -112,7 +112,8 @@
     ta[i].ctr = 0;
     ta[i].lock = lock;
     gpr_event_init(&ta[i].done);
-    GPR_ASSERT(gpr_thd_new(&thds[i], execute_many_loop, &ta[i], &options));
+    GPR_ASSERT(gpr_thd_new(&thds[i], "grpc_execute_many", execute_many_loop,
+                           &ta[i], &options));
   }
   for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
     GPR_ASSERT(gpr_event_wait(&ta[i].done,
diff --git a/test/core/iomgr/ev_epollsig_linux_test.cc b/test/core/iomgr/ev_epollsig_linux_test.cc
index ac8b2f4..94f3871 100644
--- a/test/core/iomgr/ev_epollsig_linux_test.cc
+++ b/test/core/iomgr/ev_epollsig_linux_test.cc
@@ -269,7 +269,7 @@
   for (size_t i = 0; i < GPR_ARRAY_SIZE(thds); i++) {
     gpr_thd_options opt = gpr_thd_options_default();
     gpr_thd_options_set_joinable(&opt);
-    gpr_thd_new(&thds[i], test_threading_loop, &shared, &opt);
+    gpr_thd_new(&thds[i], "test_thread", test_threading_loop, &shared, &opt);
   }
   grpc_wakeup_fd fd;
   GPR_ASSERT(GRPC_LOG_IF_ERROR("wakeup_fd_init", grpc_wakeup_fd_init(&fd)));
diff --git a/test/core/iomgr/resolve_address_posix_test.cc b/test/core/iomgr/resolve_address_posix_test.cc
index 1a5eb9a..836de42 100644
--- a/test/core/iomgr/resolve_address_posix_test.cc
+++ b/test/core/iomgr/resolve_address_posix_test.cc
@@ -104,7 +104,7 @@
 static void poll_pollset_until_request_done(args_struct* args) {
   gpr_atm_rel_store(&args->done_atm, 0);
   gpr_thd_id id;
-  gpr_thd_new(&id, actually_poll, args, nullptr);
+  gpr_thd_new(&id, "grpc_poll_pollset", actually_poll, args, nullptr);
 }
 
 static void must_succeed(grpc_exec_ctx* exec_ctx, void* argsp,
diff --git a/test/core/iomgr/wakeup_fd_cv_test.cc b/test/core/iomgr/wakeup_fd_cv_test.cc
index dc1d77a..d4e05bd 100644
--- a/test/core/iomgr/wakeup_fd_cv_test.cc
+++ b/test/core/iomgr/wakeup_fd_cv_test.cc
@@ -138,7 +138,7 @@
 
   opt = gpr_thd_options_default();
   gpr_thd_options_set_joinable(&opt);
-  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);
+  gpr_thd_new(&t_id, "grpc_background_poll", &background_poll, &pargs, &opt);
 
   // Wakeup wakeup_fd not listening for events
   GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd1) == GRPC_ERROR_NONE);
@@ -154,7 +154,7 @@
   // Pollin on socket fd
   pargs.timeout = -1;
   pargs.result = -2;
-  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);
+  gpr_thd_new(&t_id, "grpc_background_poll", &background_poll, &pargs, &opt);
   trigger_socket_event();
   gpr_thd_join(t_id);
   GPR_ASSERT(pargs.result == 1);
@@ -168,7 +168,7 @@
   // Pollin on wakeup fd
   reset_socket_event();
   pargs.result = -2;
-  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);
+  gpr_thd_new(&t_id, "grpc_background_poll", &background_poll, &pargs, &opt);
   GPR_ASSERT(grpc_wakeup_fd_wakeup(&cvfd2) == GRPC_ERROR_NONE);
   gpr_thd_join(t_id);
 
@@ -182,7 +182,7 @@
 
   // Pollin on wakeupfd before poll()
   pargs.result = -2;
-  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);
+  gpr_thd_new(&t_id, "grpc_background_poll", &background_poll, &pargs, &opt);
   gpr_thd_join(t_id);
 
   GPR_ASSERT(pargs.result == 1);
@@ -199,7 +199,7 @@
   reset_socket_event();
   GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd1) == GRPC_ERROR_NONE);
   GPR_ASSERT(grpc_wakeup_fd_consume_wakeup(&cvfd2) == GRPC_ERROR_NONE);
-  gpr_thd_new(&t_id, &background_poll, &pargs, &opt);
+  gpr_thd_new(&t_id, "grpc_background_poll", &background_poll, &pargs, &opt);
   gpr_thd_join(t_id);
 
   GPR_ASSERT(pargs.result == 0);
diff --git a/test/core/network_benchmarks/low_level_ping_pong.cc b/test/core/network_benchmarks/low_level_ping_pong.cc
index 2ae9a45..96b0745 100644
--- a/test/core/network_benchmarks/low_level_ping_pong.cc
+++ b/test/core/network_benchmarks/low_level_ping_pong.cc
@@ -583,7 +583,7 @@
   gpr_log(GPR_INFO, "Starting test %s %s %zu", client_args->strategy_name,
           socket_type, client_args->msg_size);
 
-  gpr_thd_new(&tid, server_thread_wrap, server_args, nullptr);
+  gpr_thd_new(&tid, "server_thread", server_thread_wrap, server_args, nullptr);
   client_thread(client_args);
   return 0;
 }
diff --git a/test/core/support/arena_test.cc b/test/core/support/arena_test.cc
index 244d860..ada0f43 100644
--- a/test/core/support/arena_test.cc
+++ b/test/core/support/arena_test.cc
@@ -100,7 +100,8 @@
   for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
     gpr_thd_options opt = gpr_thd_options_default();
     gpr_thd_options_set_joinable(&opt);
-    gpr_thd_new(&thds[i], concurrent_test_body, &args, &opt);
+    gpr_thd_new(&thds[i], "grpc_concurrent_test", concurrent_test_body, &args,
+                &opt);
   }
 
   gpr_event_set(&args.ev_start, (void*)1);
diff --git a/test/core/support/cpu_test.cc b/test/core/support/cpu_test.cc
index 1783ec3..6e04fee 100644
--- a/test/core/support/cpu_test.cc
+++ b/test/core/support/cpu_test.cc
@@ -110,7 +110,8 @@
   gpr_cv_init(&ct.done_cv);
   ct.is_done = 0;
   for (i = 0; i < ct.ncores * 3; i++) {
-    GPR_ASSERT(gpr_thd_new(&thd, &worker_thread, &ct, nullptr));
+    GPR_ASSERT(
+        gpr_thd_new(&thd, "grpc_cpu_test", &worker_thread, &ct, nullptr));
   }
   gpr_mu_lock(&ct.mu);
   while (!ct.is_done) {
diff --git a/test/core/support/mpscq_test.cc b/test/core/support/mpscq_test.cc
index 50ff817..1b83f7d 100644
--- a/test/core/support/mpscq_test.cc
+++ b/test/core/support/mpscq_test.cc
@@ -85,7 +85,8 @@
     ta[i].ctr = 0;
     ta[i].q = &q;
     ta[i].start = &start;
-    GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options));
+    GPR_ASSERT(
+        gpr_thd_new(&thds[i], "grpc_mt_test", test_thread, &ta[i], &options));
   }
   size_t num_done = 0;
   size_t spins = 0;
@@ -156,7 +157,8 @@
     ta[i].ctr = 0;
     ta[i].q = &q;
     ta[i].start = &start;
-    GPR_ASSERT(gpr_thd_new(&thds[i], test_thread, &ta[i], &options));
+    GPR_ASSERT(gpr_thd_new(&thds[i], "grpc_multipop_test", test_thread, &ta[i],
+                           &options));
   }
   pull_args pa;
   pa.ta = ta;
@@ -169,7 +171,8 @@
   for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) {
     gpr_thd_options options = gpr_thd_options_default();
     gpr_thd_options_set_joinable(&options);
-    GPR_ASSERT(gpr_thd_new(&pull_thds[i], pull_thread, &pa, &options));
+    GPR_ASSERT(gpr_thd_new(&pull_thds[i], "grpc_multipop_pull", pull_thread,
+                           &pa, &options));
   }
   gpr_event_set(&start, (void*)1);
   for (size_t i = 0; i < GPR_ARRAY_SIZE(pull_thds); i++) {
diff --git a/test/core/support/spinlock_test.cc b/test/core/support/spinlock_test.cc
index 3639802..58d5fcd 100644
--- a/test/core/support/spinlock_test.cc
+++ b/test/core/support/spinlock_test.cc
@@ -67,7 +67,8 @@
   for (i = 0; i != m->thread_count; i++) {
     gpr_thd_options opt = gpr_thd_options_default();
     gpr_thd_options_set_joinable(&opt);
-    GPR_ASSERT(gpr_thd_new(&m->threads[i], body, m, &opt));
+    GPR_ASSERT(
+        gpr_thd_new(&m->threads[i], "grpc_create_threads", body, m, &opt));
   }
 }
 
diff --git a/test/core/support/sync_test.cc b/test/core/support/sync_test.cc
index 86e78ce..3f534de 100644
--- a/test/core/support/sync_test.cc
+++ b/test/core/support/sync_test.cc
@@ -189,7 +189,7 @@
   gpr_thd_id id;
   int i;
   for (i = 0; i != m->threads; i++) {
-    GPR_ASSERT(gpr_thd_new(&id, body, m, nullptr));
+    GPR_ASSERT(gpr_thd_new(&id, "grpc_create_threads", body, m, nullptr));
   }
 }
 
@@ -244,7 +244,7 @@
     m = test_new(10, iterations, incr_step);
     if (extra != nullptr) {
       gpr_thd_id id;
-      GPR_ASSERT(gpr_thd_new(&id, extra, m, nullptr));
+      GPR_ASSERT(gpr_thd_new(&id, name, extra, m, nullptr));
       m->done++; /* one more thread to wait for */
     }
     test_create_threads(m, body);
diff --git a/test/core/support/thd_test.cc b/test/core/support/thd_test.cc
index 34befd8..b755bf1 100644
--- a/test/core/support/thd_test.cc
+++ b/test/core/support/thd_test.cc
@@ -74,7 +74,7 @@
   t.n = NUM_THREADS;
   t.is_done = 0;
   for (i = 0; i < NUM_THREADS; i++) {
-    GPR_ASSERT(gpr_thd_new(&thd, &thd_body, &t, nullptr));
+    GPR_ASSERT(gpr_thd_new(&thd, "grpc_thread_test", &thd_body, &t, nullptr));
   }
   gpr_mu_lock(&t.mu);
   while (!t.is_done) {
@@ -84,7 +84,8 @@
   GPR_ASSERT(t.n == 0);
   gpr_thd_options_set_joinable(&options);
   for (i = 0; i < NUM_THREADS; i++) {
-    GPR_ASSERT(gpr_thd_new(&thds[i], &thd_body_joinable, nullptr, &options));
+    GPR_ASSERT(gpr_thd_new(&thds[i], "grpc_joinable_thread_test",
+                           &thd_body_joinable, nullptr, &options));
   }
   for (i = 0; i < NUM_THREADS; i++) {
     gpr_thd_join(thds[i]);
diff --git a/test/core/support/tls_test.cc b/test/core/support/tls_test.cc
index 0f64d2e..743b10f 100644
--- a/test/core/support/tls_test.cc
+++ b/test/core/support/tls_test.cc
@@ -56,7 +56,7 @@
   gpr_thd_options_set_joinable(&opt);
 
   for (i = 0; i < NUM_THREADS; i++) {
-    gpr_thd_new(&threads[i], thd_body, nullptr, &opt);
+    gpr_thd_new(&threads[i], "grpc_tls_test", thd_body, nullptr, &opt);
   }
   for (i = 0; i < NUM_THREADS; i++) {
     gpr_thd_join(threads[i]);
diff --git a/test/core/surface/completion_queue_threading_test.cc b/test/core/surface/completion_queue_threading_test.cc
index af54e00..126d363 100644
--- a/test/core/surface/completion_queue_threading_test.cc
+++ b/test/core/surface/completion_queue_threading_test.cc
@@ -96,7 +96,8 @@
     }
     thread_states[i].cc = cc;
     thread_states[i].tag = tags[i];
-    gpr_thd_new(thread_ids + i, pluck_one, thread_states + i, &thread_options);
+    gpr_thd_new(thread_ids + i, "grpc_pluck_test", pluck_one, thread_states + i,
+                &thread_options);
   }
 
   /* wait until all other threads are plucking */
@@ -234,6 +235,7 @@
     options[i].cc = cc;
     options[i].id = optid++;
     GPR_ASSERT(gpr_thd_new(&id,
+                           i < producers ? "grpc_producer" : "grpc_consumer",
                            i < producers ? producer_thread : consumer_thread,
                            options + i, nullptr));
     gpr_event_wait(&options[i].on_started, ten_seconds_time());
diff --git a/test/core/surface/concurrent_connectivity_test.cc b/test/core/surface/concurrent_connectivity_test.cc
index c7611b0..2ff1ca3 100644
--- a/test/core/surface/concurrent_connectivity_test.cc
+++ b/test/core/surface/concurrent_connectivity_test.cc
@@ -182,7 +182,8 @@
   /* First round, no server */
   gpr_log(GPR_DEBUG, "Wave 1");
   for (size_t i = 0; i < NUM_THREADS; ++i) {
-    gpr_thd_new(&threads[i], create_loop_destroy, localhost, &options);
+    gpr_thd_new(&threads[i], "grpc_wave_1", create_loop_destroy, localhost,
+                &options);
   }
   for (size_t i = 0; i < NUM_THREADS; ++i) {
     gpr_thd_join(threads[i]);
@@ -198,10 +199,11 @@
   args.cq = grpc_completion_queue_create_for_next(nullptr);
   grpc_server_register_completion_queue(args.server, args.cq, nullptr);
   grpc_server_start(args.server);
-  gpr_thd_new(&server, server_thread, &args, &options);
+  gpr_thd_new(&server, "grpc_wave_2_server", server_thread, &args, &options);
 
   for (size_t i = 0; i < NUM_THREADS; ++i) {
-    gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options);
+    gpr_thd_new(&threads[i], "grpc_wave_2", create_loop_destroy, args.addr,
+                &options);
   }
   for (size_t i = 0; i < NUM_THREADS; ++i) {
     gpr_thd_join(threads[i]);
@@ -218,11 +220,13 @@
   args.pollset = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
   grpc_pollset_init(args.pollset, &args.mu);
   gpr_event_init(&args.ready);
-  gpr_thd_new(&server, bad_server_thread, &args, &options);
+  gpr_thd_new(&server, "grpc_wave_3_server", bad_server_thread, &args,
+              &options);
   gpr_event_wait(&args.ready, gpr_inf_future(GPR_CLOCK_MONOTONIC));
 
   for (size_t i = 0; i < NUM_THREADS; ++i) {
-    gpr_thd_new(&threads[i], create_loop_destroy, args.addr, &options);
+    gpr_thd_new(&threads[i], "grpc_wave_3", create_loop_destroy, args.addr,
+                &options);
   }
   for (size_t i = 0; i < NUM_THREADS; ++i) {
     gpr_thd_join(threads[i]);
@@ -280,7 +284,8 @@
   gpr_thd_options_set_joinable(&options);
 
   for (size_t i = 0; i < NUM_THREADS; ++i) {
-    gpr_thd_new(&threads[i], watches_with_short_timeouts, localhost, &options);
+    gpr_thd_new(&threads[i], "grpc_short_watches", watches_with_short_timeouts,
+                localhost, &options);
   }
   for (size_t i = 0; i < NUM_THREADS; ++i) {
     gpr_thd_join(threads[i]);
diff --git a/test/core/surface/sequential_connectivity_test.cc b/test/core/surface/sequential_connectivity_test.cc
index 015db92..11d0aa7 100644
--- a/test/core/surface/sequential_connectivity_test.cc
+++ b/test/core/surface/sequential_connectivity_test.cc
@@ -70,7 +70,7 @@
   gpr_thd_id server_thread;
   gpr_thd_options thdopt = gpr_thd_options_default();
   gpr_thd_options_set_joinable(&thdopt);
-  gpr_thd_new(&server_thread, server_thread_func, &sta, &thdopt);
+  gpr_thd_new(&server_thread, "grpc_server", server_thread_func, &sta, &thdopt);
 
   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
   grpc_channel* channels[NUM_CONNECTIONS];
diff --git a/test/cpp/grpclb/grpclb_test.cc b/test/cpp/grpclb/grpclb_test.cc
index ca846c7..a469fbb 100644
--- a/test/cpp/grpclb/grpclb_test.cc
+++ b/test/cpp/grpclb/grpclb_test.cc
@@ -703,14 +703,15 @@
       tf.lb_backends[i].lb_token_prefix = "";
     }
     setup_server("127.0.0.1", &tf.lb_backends[i]);
-    gpr_thd_new(&tf.lb_backends[i].tid, fork_backend_server, &tf.lb_backends[i],
-                &options);
+    gpr_thd_new(&tf.lb_backends[i].tid, "grpclb_backend", fork_backend_server,
+                &tf.lb_backends[i], &options);
   }
 
   tf.lb_server.lb_token_prefix = LB_TOKEN_PREFIX;
   tf.lb_server.balancer_name = BALANCERS_NAME;
   setup_server("127.0.0.1", &tf.lb_server);
-  gpr_thd_new(&tf.lb_server.tid, fork_lb_server, &tf.lb_server, &options);
+  gpr_thd_new(&tf.lb_server.tid, "grpclb_server", fork_lb_server, &tf.lb_server,
+              &options);
   setup_client(&tf.lb_server, tf.lb_backends, &tf.client);
   return tf;
 }