xref: /aosp_15_r20/external/grpc-grpc/test/cpp/naming/cancel_ares_query_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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 <stdio.h>
20 #include <string.h>
21 
22 #include <string>
23 
24 #include <gmock/gmock.h>
25 
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/str_format.h"
28 
29 #include <grpc/byte_buffer.h>
30 #include <grpc/grpc.h>
31 #include <grpc/grpc_security.h>
32 #include <grpc/support/alloc.h>
33 #include <grpc/support/log.h>
34 #include <grpc/support/time.h>
35 
36 #include "src/core/lib/channel/channel_args.h"
37 #include "src/core/lib/config/config_vars.h"
38 #include "src/core/lib/config/core_configuration.h"
39 #include "src/core/lib/debug/stats.h"
40 #include "src/core/lib/debug/stats_data.h"
41 #include "src/core/lib/event_engine/ares_resolver.h"
42 #include "src/core/lib/event_engine/default_event_engine.h"
43 #include "src/core/lib/experiments/experiments.h"
44 #include "src/core/lib/gpr/string.h"
45 #include "src/core/lib/gprpp/crash.h"
46 #include "src/core/lib/gprpp/orphanable.h"
47 #include "src/core/lib/gprpp/thd.h"
48 #include "src/core/lib/gprpp/work_serializer.h"
49 #include "src/core/lib/iomgr/iomgr.h"
50 #include "src/core/lib/iomgr/pollset.h"
51 #include "src/core/lib/iomgr/pollset_set.h"
52 #include "src/core/resolver/dns/c_ares/grpc_ares_wrapper.h"
53 #include "src/core/resolver/resolver.h"
54 #include "src/core/resolver/resolver_registry.h"
55 #include "test/core/end2end/cq_verifier.h"
56 #include "test/core/util/cmdline.h"
57 #include "test/core/util/fake_udp_and_tcp_server.h"
58 #include "test/core/util/port.h"
59 #include "test/core/util/socket_use_after_close_detector.h"
60 #include "test/core/util/test_config.h"
61 #include "test/cpp/util/test_config.h"
62 
63 #ifdef GPR_WINDOWS
64 #include "src/core/lib/iomgr/sockaddr_windows.h"
65 #include "src/core/lib/iomgr/socket_windows.h"
66 #define BAD_SOCKET_RETURN_VAL INVALID_SOCKET
67 #else
68 #include "src/core/lib/iomgr/sockaddr_posix.h"
69 #define BAD_SOCKET_RETURN_VAL (-1)
70 #endif
71 
72 namespace {
73 
74 using ::grpc_event_engine::experimental::GetDefaultEventEngine;
75 
Tag(intptr_t t)76 void* Tag(intptr_t t) { return reinterpret_cast<void*>(t); }
77 
FiveSecondsFromNow(void)78 gpr_timespec FiveSecondsFromNow(void) {
79   return grpc_timeout_seconds_to_deadline(5);
80 }
81 
DrainCq(grpc_completion_queue * cq)82 void DrainCq(grpc_completion_queue* cq) {
83   grpc_event ev;
84   do {
85     ev = grpc_completion_queue_next(cq, FiveSecondsFromNow(), nullptr);
86   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
87 }
88 
EndTest(grpc_channel * client,grpc_completion_queue * cq)89 void EndTest(grpc_channel* client, grpc_completion_queue* cq) {
90   grpc_channel_destroy(client);
91   grpc_completion_queue_shutdown(cq);
92   DrainCq(cq);
93   grpc_completion_queue_destroy(cq);
94 }
95 
96 struct ArgsStruct {
97   gpr_atm done_atm;
98   gpr_mu* mu;
99   grpc_pollset* pollset;
100   grpc_pollset_set* pollset_set;
101   std::shared_ptr<grpc_core::WorkSerializer> lock;
102   grpc_channel_args* channel_args;
103 };
104 
ArgsInit(ArgsStruct * args)105 void ArgsInit(ArgsStruct* args) {
106   args->pollset = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
107   grpc_pollset_init(args->pollset, &args->mu);
108   args->pollset_set = grpc_pollset_set_create();
109   grpc_pollset_set_add_pollset(args->pollset_set, args->pollset);
110   args->lock = std::make_shared<grpc_core::WorkSerializer>(
111       grpc_event_engine::experimental::GetDefaultEventEngine());
112   gpr_atm_rel_store(&args->done_atm, 0);
113   args->channel_args = nullptr;
114 }
115 
DoNothing(void *,grpc_error_handle)116 void DoNothing(void* /*arg*/, grpc_error_handle /*error*/) {}
117 
ArgsFinish(ArgsStruct * args)118 void ArgsFinish(ArgsStruct* args) {
119   grpc_pollset_set_del_pollset(args->pollset_set, args->pollset);
120   grpc_pollset_set_destroy(args->pollset_set);
121   grpc_closure DoNothing_cb;
122   GRPC_CLOSURE_INIT(&DoNothing_cb, DoNothing, nullptr,
123                     grpc_schedule_on_exec_ctx);
124   grpc_pollset_shutdown(args->pollset, &DoNothing_cb);
125   // exec_ctx needs to be flushed before calling grpc_pollset_destroy()
126   grpc_channel_args_destroy(args->channel_args);
127   grpc_core::ExecCtx::Get()->Flush();
128   grpc_pollset_destroy(args->pollset);
129   gpr_free(args->pollset);
130 }
131 
PollPollsetUntilRequestDone(ArgsStruct * args)132 void PollPollsetUntilRequestDone(ArgsStruct* args) {
133   while (true) {
134     bool done = gpr_atm_acq_load(&args->done_atm) != 0;
135     if (done) {
136       break;
137     }
138     grpc_pollset_worker* worker = nullptr;
139     grpc_core::ExecCtx exec_ctx;
140     gpr_mu_lock(args->mu);
141     GRPC_LOG_IF_ERROR("pollset_work",
142                       grpc_pollset_work(args->pollset, &worker,
143                                         grpc_core::Timestamp::InfFuture()));
144     gpr_mu_unlock(args->mu);
145   }
146 }
147 
148 class AssertFailureResultHandler : public grpc_core::Resolver::ResultHandler {
149  public:
AssertFailureResultHandler(ArgsStruct * args)150   explicit AssertFailureResultHandler(ArgsStruct* args) : args_(args) {}
151 
~AssertFailureResultHandler()152   ~AssertFailureResultHandler() override {
153     gpr_atm_rel_store(&args_->done_atm, 1);
154     gpr_mu_lock(args_->mu);
155     GRPC_LOG_IF_ERROR("pollset_kick",
156                       grpc_pollset_kick(args_->pollset, nullptr));
157     gpr_mu_unlock(args_->mu);
158   }
159 
ReportResult(grpc_core::Resolver::Result)160   void ReportResult(grpc_core::Resolver::Result /*result*/) override {
161     grpc_core::Crash("unreachable");
162   }
163 
164  private:
165   ArgsStruct* args_;
166 };
167 
TestCancelActiveDNSQuery(ArgsStruct * args)168 void TestCancelActiveDNSQuery(ArgsStruct* args) {
169   grpc_core::testing::FakeUdpAndTcpServer fake_dns_server(
170       grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
171           kWaitForClientToSendFirstBytes,
172       grpc_core::testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
173   std::string client_target = absl::StrFormat(
174       "dns://[::1]:%d/dont-care-since-wont-be-resolved.test.com:1234",
175       fake_dns_server.port());
176   // create resolver and resolve
177   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
178       grpc_core::CoreConfiguration::Get().resolver_registry().CreateResolver(
179           client_target.c_str(),
180           grpc_core::ChannelArgs().SetObject(GetDefaultEventEngine()),
181           args->pollset_set, args->lock,
182           std::unique_ptr<grpc_core::Resolver::ResultHandler>(
183               new AssertFailureResultHandler(args)));
184   resolver->StartLocked();
185   // Without resetting and causing resolver shutdown, the
186   // PollPollsetUntilRequestDone call should never finish.
187   resolver.reset();
188   grpc_core::ExecCtx::Get()->Flush();
189   PollPollsetUntilRequestDone(args);
190   ArgsFinish(args);
191 }
192 
193 class CancelDuringAresQuery : public ::testing::Test {
194  protected:
SetUpTestSuite()195   static void SetUpTestSuite() {
196     grpc_core::ConfigVars::Overrides overrides;
197     overrides.dns_resolver = "ares";
198     grpc_core::ConfigVars::SetOverrides(overrides);
199     grpc_init();
200   }
201 
TearDownTestSuite()202   static void TearDownTestSuite() { grpc_shutdown(); }
203 };
204 
TEST_F(CancelDuringAresQuery,TestCancelActiveDNSQuery)205 TEST_F(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
206   grpc_core::ExecCtx exec_ctx;
207   ArgsStruct args;
208   ArgsInit(&args);
209   TestCancelActiveDNSQuery(&args);
210 }
211 
212 #ifdef GPR_WINDOWS
213 
MaybePollArbitraryPollsetTwice()214 void MaybePollArbitraryPollsetTwice() {
215   grpc_pollset* pollset = (grpc_pollset*)gpr_zalloc(grpc_pollset_size());
216   gpr_mu* mu;
217   grpc_pollset_init(pollset, &mu);
218   grpc_pollset_worker* worker = nullptr;
219   // Make a zero timeout poll
220   gpr_mu_lock(mu);
221   GRPC_LOG_IF_ERROR(
222       "pollset_work",
223       grpc_pollset_work(pollset, &worker, grpc_core::Timestamp::Now()));
224   gpr_mu_unlock(mu);
225   grpc_core::ExecCtx::Get()->Flush();
226   // Make a second zero-timeout poll (in case the first one
227   // short-circuited by picking up a previous "kick")
228   gpr_mu_lock(mu);
229   GRPC_LOG_IF_ERROR(
230       "pollset_work",
231       grpc_pollset_work(pollset, &worker, grpc_core::Timestamp::Now()));
232   gpr_mu_unlock(mu);
233   grpc_core::ExecCtx::Get()->Flush();
234   grpc_pollset_destroy(pollset);
235   gpr_free(pollset);
236 }
237 
238 #else
239 
MaybePollArbitraryPollsetTwice()240 void MaybePollArbitraryPollsetTwice() {}
241 
242 #endif
243 
TEST_F(CancelDuringAresQuery,TestFdsAreDeletedFromPollsetSet)244 TEST_F(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) {
245   grpc_core::ExecCtx exec_ctx;
246   ArgsStruct args;
247   ArgsInit(&args);
248   // Add fake_other_pollset_set into the mix to test
249   // that we're explicitly deleting fd's from their pollset.
250   // If we aren't doing so, then the remaining presence of
251   // "fake_other_pollset_set" after the request is done and the resolver
252   // pollset set is destroyed should keep the resolver's fd alive and
253   // fail the test.
254   grpc_pollset_set* fake_other_pollset_set = grpc_pollset_set_create();
255   grpc_pollset_set_add_pollset_set(fake_other_pollset_set, args.pollset_set);
256   // Note that running the cancellation c-ares test is somewhat irrelevant for
257   // this test. This test only cares about what happens to fd's that c-ares
258   // opens.
259   TestCancelActiveDNSQuery(&args);
260   // This test relies on the assumption that cancelling a c-ares query
261   // will flush out all callbacks on the current exec ctx, which is true
262   // on posix platforms but not on Windows, because fd shutdown on Windows
263   // requires a trip through the polling loop to schedule the callback.
264   // So we need to do extra polling work on Windows to free things up.
265   MaybePollArbitraryPollsetTwice();
266   EXPECT_EQ(grpc_iomgr_count_objects_for_testing(), 0u);
267   grpc_pollset_set_destroy(fake_other_pollset_set);
268 }
269 
270 std::string kFakeName = "dont-care-since-wont-be-resolved.test.com:1234";
271 
TestCancelDuringActiveQuery(grpc_status_code expected_status_code,absl::string_view expected_error_message_substring,gpr_timespec rpc_deadline,int dns_query_timeout_ms,int fake_dns_server_port)272 void TestCancelDuringActiveQuery(
273     grpc_status_code expected_status_code,
274     absl::string_view expected_error_message_substring,
275     gpr_timespec rpc_deadline, int dns_query_timeout_ms,
276     int fake_dns_server_port) {
277   // Create a call that will try to use the fake DNS server
278   std::string client_target =
279       absl::StrFormat("dns://[::1]:%d/%s", fake_dns_server_port, kFakeName);
280   grpc_channel_args* client_args = nullptr;
281   if (dns_query_timeout_ms >= 0) {
282     grpc_arg arg;
283     arg.type = GRPC_ARG_INTEGER;
284     arg.key = const_cast<char*>(GRPC_ARG_DNS_ARES_QUERY_TIMEOUT_MS);
285     arg.value.integer = dns_query_timeout_ms;
286     client_args = grpc_channel_args_copy_and_add(nullptr, &arg, 1);
287   }
288   grpc_channel_credentials* creds = grpc_insecure_credentials_create();
289   grpc_channel* client =
290       grpc_channel_create(client_target.c_str(), creds, client_args);
291   grpc_channel_credentials_release(creds);
292   grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
293   grpc_core::CqVerifier cqv(cq);
294   grpc_call* call = grpc_channel_create_call(
295       client, nullptr, GRPC_PROPAGATE_DEFAULTS, cq,
296       grpc_slice_from_static_string("/foo"), nullptr, rpc_deadline, nullptr);
297   GPR_ASSERT(call);
298   grpc_metadata_array initial_metadata_recv;
299   grpc_metadata_array trailing_metadata_recv;
300   grpc_metadata_array request_metadata_recv;
301   grpc_metadata_array_init(&initial_metadata_recv);
302   grpc_metadata_array_init(&trailing_metadata_recv);
303   grpc_metadata_array_init(&request_metadata_recv);
304   grpc_call_details call_details;
305   grpc_call_details_init(&call_details);
306   grpc_status_code status;
307   const char* error_string;
308   grpc_slice details;
309   // Set ops for client the request
310   grpc_op ops_base[6];
311   memset(ops_base, 0, sizeof(ops_base));
312   grpc_op* op = ops_base;
313   op->op = GRPC_OP_SEND_INITIAL_METADATA;
314   op->data.send_initial_metadata.count = 0;
315   op->flags = 0;
316   op->reserved = nullptr;
317   op++;
318   op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
319   op->flags = 0;
320   op->reserved = nullptr;
321   op++;
322   op->op = GRPC_OP_RECV_INITIAL_METADATA;
323   op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
324   op->flags = 0;
325   op->reserved = nullptr;
326   op++;
327   op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
328   op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
329   op->data.recv_status_on_client.status = &status;
330   op->data.recv_status_on_client.status_details = &details;
331   op->data.recv_status_on_client.error_string = &error_string;
332   op->flags = 0;
333   op->reserved = nullptr;
334   op++;
335   // Run the call and sanity check it failed as expected
336   grpc_call_error error = grpc_call_start_batch(
337       call, ops_base, static_cast<size_t>(op - ops_base), Tag(1), nullptr);
338   EXPECT_EQ(GRPC_CALL_OK, error);
339   cqv.Expect(Tag(1), true);
340   cqv.Verify();
341   EXPECT_EQ(status, expected_status_code);
342   EXPECT_THAT(std::string(error_string),
343               testing::HasSubstr(expected_error_message_substring));
344   // Teardown
345   grpc_channel_args_destroy(client_args);
346   grpc_slice_unref(details);
347   gpr_free(const_cast<char*>(error_string));
348   grpc_metadata_array_destroy(&initial_metadata_recv);
349   grpc_metadata_array_destroy(&trailing_metadata_recv);
350   grpc_metadata_array_destroy(&request_metadata_recv);
351   grpc_call_details_destroy(&call_details);
352   grpc_call_unref(call);
353   EndTest(client, cq);
354 }
355 
TEST_F(CancelDuringAresQuery,TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful)356 TEST_F(CancelDuringAresQuery,
357        TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful) {
358   grpc_core::testing::SocketUseAfterCloseDetector
359       socket_use_after_close_detector;
360   grpc_core::testing::FakeUdpAndTcpServer fake_dns_server(
361       grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
362           kWaitForClientToSendFirstBytes,
363       grpc_core::testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
364   grpc_status_code expected_status_code = GRPC_STATUS_DEADLINE_EXCEEDED;
365   // The RPC deadline should go off well before the DNS resolution
366   // timeout fires.
367   gpr_timespec rpc_deadline = grpc_timeout_milliseconds_to_deadline(100);
368   int dns_query_timeout_ms = -1;  // don't set query timeout
369   TestCancelDuringActiveQuery(
370       expected_status_code, "" /* expected error message substring */,
371       rpc_deadline, dns_query_timeout_ms, fake_dns_server.port());
372 }
373 
TEST_F(CancelDuringAresQuery,TestHitDeadlineAndDestroyChannelDuringAresResolutionWithQueryTimeoutIsGraceful)374 TEST_F(
375     CancelDuringAresQuery,
376     TestHitDeadlineAndDestroyChannelDuringAresResolutionWithQueryTimeoutIsGraceful) {
377   grpc_core::testing::SocketUseAfterCloseDetector
378       socket_use_after_close_detector;
379   grpc_core::testing::FakeUdpAndTcpServer fake_dns_server(
380       grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
381           kWaitForClientToSendFirstBytes,
382       grpc_core::testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
383   grpc_status_code expected_status_code = GRPC_STATUS_UNAVAILABLE;
384   std::string expected_error_message_substring;
385   if (grpc_core::IsEventEngineDnsEnabled()) {
386     expected_error_message_substring =
387         absl::StrCat("errors resolving ", kFakeName);
388   } else {
389     expected_error_message_substring =
390         absl::StrCat("DNS resolution failed for ", kFakeName);
391   }
392   // The DNS resolution timeout should fire well before the
393   // RPC's deadline expires.
394   gpr_timespec rpc_deadline = grpc_timeout_seconds_to_deadline(10);
395   int dns_query_timeout_ms = 1;
396   TestCancelDuringActiveQuery(expected_status_code,
397                               expected_error_message_substring, rpc_deadline,
398                               dns_query_timeout_ms, fake_dns_server.port());
399 }
400 
TEST_F(CancelDuringAresQuery,TestHitDeadlineAndDestroyChannelDuringAresResolutionWithZeroQueryTimeoutIsGraceful)401 TEST_F(
402     CancelDuringAresQuery,
403     TestHitDeadlineAndDestroyChannelDuringAresResolutionWithZeroQueryTimeoutIsGraceful) {
404   grpc_core::testing::SocketUseAfterCloseDetector
405       socket_use_after_close_detector;
406   grpc_core::testing::FakeUdpAndTcpServer fake_dns_server(
407       grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
408           kWaitForClientToSendFirstBytes,
409       grpc_core::testing::FakeUdpAndTcpServer::CloseSocketUponCloseFromPeer);
410   grpc_status_code expected_status_code = GRPC_STATUS_DEADLINE_EXCEEDED;
411   // The RPC deadline should go off well before the DNS resolution
412   // timeout fires.
413   gpr_timespec rpc_deadline = grpc_timeout_milliseconds_to_deadline(100);
414   int dns_query_timeout_ms = 0;  // disable query timeouts
415   TestCancelDuringActiveQuery(
416       expected_status_code, "" /* expected error message substring */,
417       rpc_deadline, dns_query_timeout_ms, fake_dns_server.port());
418 }
419 
TEST_F(CancelDuringAresQuery,TestQueryFailsBecauseTcpServerClosesSocket)420 TEST_F(CancelDuringAresQuery, TestQueryFailsBecauseTcpServerClosesSocket) {
421   grpc_core::testing::SocketUseAfterCloseDetector
422       socket_use_after_close_detector;
423   // Use a fake TCP server that immediately closes the socket and causes
424   // c-ares to pick up a socket read error, while the previous socket
425   // connect/writes succeeded. Meanwhile, force c-ares to only use TCP.
426   // The goal is to hit a socket use-after-close bug described in
427   // https://github.com/grpc/grpc/pull/33871.
428   grpc_core::testing::FakeUdpAndTcpServer fake_dns_server(
429       grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
430           kWaitForClientToSendFirstBytes,
431       grpc_core::testing::FakeUdpAndTcpServer::
432           CloseSocketUponReceivingBytesFromPeer);
433   if (grpc_core::IsEventEngineDnsEnabled()) {
434     g_event_engine_grpc_ares_test_only_force_tcp = true;
435   } else {
436     g_grpc_ares_test_only_force_tcp = true;
437   }
438   grpc_status_code expected_status_code = GRPC_STATUS_UNAVAILABLE;
439   std::string expected_error_message_substring;
440   if (grpc_core::IsEventEngineDnsEnabled()) {
441     expected_error_message_substring =
442         absl::StrCat("errors resolving ", kFakeName);
443   } else {
444     expected_error_message_substring =
445         absl::StrCat("DNS resolution failed for ", kFakeName);
446   }
447   // Don't really care about the deadline - we should quickly hit a DNS
448   // resolution failure.
449   gpr_timespec rpc_deadline = grpc_timeout_seconds_to_deadline(100);
450   int dns_query_timeout_ms = -1;  // don't set query timeout
451   TestCancelDuringActiveQuery(expected_status_code,
452                               expected_error_message_substring, rpc_deadline,
453                               dns_query_timeout_ms, fake_dns_server.port());
454   if (grpc_core::IsEventEngineDnsEnabled()) {
455     g_event_engine_grpc_ares_test_only_force_tcp = false;
456   } else {
457     g_grpc_ares_test_only_force_tcp = false;
458   }
459 }
460 
461 // This test is meant to repro a bug noticed in internal issue b/297538255.
462 // The general issue is the loop in
463 // https://github.com/grpc/grpc/blob/f6a994229e72bc771963706de7a0cd8aa9150bb6/src/core/resolver/dns/c_ares/grpc_ares_wrapper.cc#L371.
464 // The problem with that loop is that c-ares *can* in certain situations stop
465 // caring about the fd being processed without reading all of the data out of
466 // the read buffer. In that case, we keep looping because
467 // IsFdStillReadableLocked() keeps returning true, but we never make progress.
468 // Meanwhile, we are holding a lock which prevents cancellation or timeouts from
469 // kicking in, and thus we spin-loop forever.
470 //
471 // At the time of writing, this test case illustrates one way to hit that bug.
472 // It works as follows:
473 //   1) We force c-ares to use TCP for its DNS queries
474 //   2) We stand up a fake DNS server that, for each incoming connection, sends
475 //      three all-zero bytes and then closes the socket.
476 //   3) When the c-ares library receives the three-zero-byte response from the
477 //      DNS server, it parses the first two-bytes as a length field:
478 //      https://github.com/c-ares/c-ares/blob/6360e96b5cf8e5980c887ce58ef727e53d77243a/src/lib/ares_process.c#L410.
479 //   4) Because the first two bytes were zero, c-ares attempts to malloc a
480 //      zero-length buffer:
481 //      https://github.com/c-ares/c-ares/blob/6360e96b5cf8e5980c887ce58ef727e53d77243a/src/lib/ares_process.c#L428.
482 //   5) Because c-ares' default_malloc(0) returns NULL
483 //      (https://github.com/c-ares/c-ares/blob/7f3262312f246556d8c1bdd8ccc1844847f42787/src/lib/ares_library_init.c#L38),
484 //      c-ares invokes handle_error and stops reading on the socket:
485 //      https://github.com/c-ares/c-ares/blob/6360e96b5cf8e5980c887ce58ef727e53d77243a/src/lib/ares_process.c#L430.
486 //   6) Because we overwrite the socket "close" method, c-ares attempt to close
487 //      the socket in handle_error does nothing except for removing the socket
488 //      from ARES_GETSOCK_READABLE:
489 //      https://github.com/grpc/grpc/blob/f6a994229e72bc771963706de7a0cd8aa9150bb6/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc#L156.
490 //   7) Because there is still one byte left in the TCP read buffer,
491 //      IsFdStillReadableLocked will keep returning true:
492 //      https://github.com/grpc/grpc/blob/f6a994229e72bc771963706de7a0cd8aa9150bb6/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc#L82.
493 //      But c-ares will never try to read from that socket again, so we have an
494 //      infinite busy loop.
TEST_F(CancelDuringAresQuery,TestQueryFailsWithDataRemainingInReadBuffer)495 TEST_F(CancelDuringAresQuery, TestQueryFailsWithDataRemainingInReadBuffer) {
496   if (grpc_core::IsEventEngineDnsEnabled()) {
497     g_event_engine_grpc_ares_test_only_force_tcp = true;
498   } else {
499     g_grpc_ares_test_only_force_tcp = true;
500   }
501   grpc_core::testing::SocketUseAfterCloseDetector
502       socket_use_after_close_detector;
503   grpc_core::testing::FakeUdpAndTcpServer fake_dns_server(
504       grpc_core::testing::FakeUdpAndTcpServer::AcceptMode::
505           kWaitForClientToSendFirstBytes,
506       grpc_core::testing::FakeUdpAndTcpServer::SendThreeAllZeroBytes);
507   grpc_status_code expected_status_code = GRPC_STATUS_UNAVAILABLE;
508   // Don't really care about the deadline - we'll hit a DNS
509   // resolution failure quickly in any case.
510   gpr_timespec rpc_deadline = grpc_timeout_seconds_to_deadline(100);
511   int dns_query_timeout_ms = -1;  // don't set query timeout
512   TestCancelDuringActiveQuery(
513       expected_status_code, "" /* expected error message substring */,
514       rpc_deadline, dns_query_timeout_ms, fake_dns_server.port());
515   if (grpc_core::IsEventEngineDnsEnabled()) {
516     g_event_engine_grpc_ares_test_only_force_tcp = false;
517   } else {
518     g_grpc_ares_test_only_force_tcp = false;
519   }
520 }
521 
522 }  // namespace
523 
main(int argc,char ** argv)524 int main(int argc, char** argv) {
525   ::testing::InitGoogleTest(&argc, argv);
526   grpc::testing::InitTest(&argc, &argv, true);
527   grpc::testing::TestEnvironment env(&argc, argv);
528   auto result = RUN_ALL_TESTS();
529   return result;
530 }
531