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([¬ification]() { 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