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