Fix tcp_client memory leak and add test for it

pull/27032/head
AJ Heller 4 years ago
parent 4c48bbb033
commit ca0c8c4f0b
  1. 1
      src/core/lib/iomgr/tcp_client_posix.cc
  2. 46
      test/core/iomgr/tcp_client_posix_test.cc

@ -357,6 +357,7 @@ static void tcp_connect(grpc_closure* closure, grpc_endpoint** ep,
*ep = nullptr;
if ((error = grpc_tcp_client_prepare_fd(channel_args, addr, &mapped_addr,
&fd)) != GRPC_ERROR_NONE) {
grpc_slice_allocator_destroy(slice_allocator);
grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, error);
return;
}

@ -78,6 +78,7 @@ static void must_fail(void* /*arg*/, grpc_error_handle error) {
}
void test_succeeds(void) {
gpr_log(GPR_ERROR, "---- starting test_succeeds() ----");
grpc_resolved_address resolved_addr;
struct sockaddr_in* addr =
reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
@ -87,8 +88,6 @@ void test_succeeds(void) {
grpc_closure done;
grpc_core::ExecCtx exec_ctx;
gpr_log(GPR_DEBUG, "test_succeeds");
memset(&resolved_addr, 0, sizeof(resolved_addr));
resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
@ -135,9 +134,11 @@ void test_succeeds(void) {
}
gpr_mu_unlock(g_mu);
gpr_log(GPR_ERROR, "---- finished test_succeeds() ----");
}
void test_fails(void) {
gpr_log(GPR_ERROR, "---- starting test_fails() ----");
grpc_resolved_address resolved_addr;
struct sockaddr_in* addr =
reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
@ -145,8 +146,6 @@ void test_fails(void) {
grpc_closure done;
grpc_core::ExecCtx exec_ctx;
gpr_log(GPR_DEBUG, "test_fails");
memset(&resolved_addr, 0, sizeof(resolved_addr));
resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
@ -184,6 +183,43 @@ void test_fails(void) {
}
gpr_mu_unlock(g_mu);
gpr_log(GPR_ERROR, "---- finished test_fails() ----");
}
void test_fails_bad_addr_no_leak(void) {
gpr_log(GPR_ERROR, "---- starting test_fails_bad_addr_no_leak() ----");
grpc_resolved_address resolved_addr;
struct sockaddr_in* addr =
reinterpret_cast<struct sockaddr_in*>(resolved_addr.addr);
int connections_complete_before;
grpc_closure done;
grpc_core::ExecCtx exec_ctx;
memset(&resolved_addr, 0, sizeof(resolved_addr));
resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
// force `grpc_tcp_client_prepare_fd` to fail. contrived, but effective.
addr->sin_family = AF_BLUETOOTH;
gpr_mu_lock(g_mu);
connections_complete_before = g_connections_complete;
gpr_mu_unlock(g_mu);
// connect to an invalid address.
GRPC_CLOSURE_INIT(&done, must_fail, nullptr, grpc_schedule_on_exec_ctx);
grpc_tcp_client_connect(
&done, &g_connecting, grpc_slice_allocator_create_unlimited(),
g_pollset_set, nullptr, &resolved_addr, GRPC_MILLIS_INF_FUTURE);
gpr_mu_lock(g_mu);
while (g_connections_complete == connections_complete_before) {
grpc_pollset_worker* worker = nullptr;
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"pollset_work",
grpc_pollset_work(g_pollset, &worker,
grpc_timespec_to_millis_round_up(
grpc_timeout_seconds_to_deadline(5)))));
gpr_mu_unlock(g_mu);
grpc_core::ExecCtx::Get()->Flush();
gpr_mu_lock(g_mu);
}
gpr_mu_unlock(g_mu);
gpr_log(GPR_ERROR, "---- finished test_fails_bad_addr_no_leak() ----");
}
static void destroy_pollset(void* p, grpc_error_handle /*error*/) {
@ -203,8 +239,8 @@ int main(int argc, char** argv) {
grpc_pollset_set_add_pollset(g_pollset_set, g_pollset);
test_succeeds();
gpr_log(GPR_ERROR, "End of first test");
test_fails();
test_fails_bad_addr_no_leak();
grpc_pollset_set_destroy(g_pollset_set);
GRPC_CLOSURE_INIT(&destroyed, destroy_pollset, g_pollset,
grpc_schedule_on_exec_ctx);

Loading…
Cancel
Save