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