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 <gflags/gflags.h>
23 #include <gmock/gmock.h>
24
25 #include <grpc/byte_buffer.h>
26 #include <grpc/grpc.h>
27 #include <grpc/support/alloc.h>
28 #include <grpc/support/log.h>
29 #include <grpc/support/time.h>
30 #include "include/grpc/support/string_util.h"
31 #include "src/core/ext/filters/client_channel/resolver.h"
32 #include "src/core/ext/filters/client_channel/resolver_registry.h"
33 #include "src/core/lib/channel/channel_args.h"
34 #include "src/core/lib/debug/stats.h"
35 #include "src/core/lib/gpr/env.h"
36 #include "src/core/lib/gpr/host_port.h"
37 #include "src/core/lib/gpr/string.h"
38 #include "src/core/lib/gprpp/orphanable.h"
39 #include "src/core/lib/gprpp/thd.h"
40 #include "src/core/lib/iomgr/combiner.h"
41 #include "src/core/lib/iomgr/pollset.h"
42 #include "src/core/lib/iomgr/pollset_set.h"
43 #include "test/core/end2end/cq_verifier.h"
44 #include "test/core/util/cmdline.h"
45 #include "test/core/util/port.h"
46 #include "test/core/util/test_config.h"
47
48 #ifdef GPR_WINDOWS
49 #include "src/core/lib/iomgr/sockaddr_windows.h"
50 #include "src/core/lib/iomgr/socket_windows.h"
51 #define BAD_SOCKET_RETURN_VAL INVALID_SOCKET
52 #else
53 #include "src/core/lib/iomgr/sockaddr_posix.h"
54 #define BAD_SOCKET_RETURN_VAL -1
55 #endif
56
57 namespace {
58
Tag(intptr_t t)59 void* Tag(intptr_t t) { return (void*)t; }
60
FiveSecondsFromNow(void)61 gpr_timespec FiveSecondsFromNow(void) {
62 return grpc_timeout_seconds_to_deadline(5);
63 }
64
DrainCq(grpc_completion_queue * cq)65 void DrainCq(grpc_completion_queue* cq) {
66 grpc_event ev;
67 do {
68 ev = grpc_completion_queue_next(cq, FiveSecondsFromNow(), nullptr);
69 } while (ev.type != GRPC_QUEUE_SHUTDOWN);
70 }
71
EndTest(grpc_channel * client,grpc_completion_queue * cq)72 void EndTest(grpc_channel* client, grpc_completion_queue* cq) {
73 grpc_channel_destroy(client);
74 grpc_completion_queue_shutdown(cq);
75 DrainCq(cq);
76 grpc_completion_queue_destroy(cq);
77 }
78
79 class FakeNonResponsiveDNSServer {
80 public:
FakeNonResponsiveDNSServer(int port)81 FakeNonResponsiveDNSServer(int port) {
82 socket_ = socket(AF_INET6, SOCK_DGRAM, 0);
83 if (socket_ == BAD_SOCKET_RETURN_VAL) {
84 gpr_log(GPR_DEBUG, "Failed to create UDP ipv6 socket");
85 abort();
86 }
87 sockaddr_in6 addr;
88 memset(&addr, 0, sizeof(addr));
89 addr.sin6_family = AF_INET6;
90 addr.sin6_port = htons(port);
91 ((char*)&addr.sin6_addr)[15] = 1;
92 if (bind(socket_, (const sockaddr*)&addr, sizeof(addr)) != 0) {
93 gpr_log(GPR_DEBUG, "Failed to bind UDP ipv6 socket to [::1]:%d", port);
94 abort();
95 }
96 }
~FakeNonResponsiveDNSServer()97 ~FakeNonResponsiveDNSServer() {
98 #ifdef GPR_WINDOWS
99 closesocket(socket_);
100 #else
101 close(socket_);
102 #endif
103 }
104
105 private:
106 int socket_;
107 };
108
109 struct ArgsStruct {
110 gpr_atm done_atm;
111 gpr_mu* mu;
112 grpc_pollset* pollset;
113 grpc_pollset_set* pollset_set;
114 grpc_combiner* lock;
115 grpc_channel_args* channel_args;
116 };
117
ArgsInit(ArgsStruct * args)118 void ArgsInit(ArgsStruct* args) {
119 args->pollset = (grpc_pollset*)gpr_zalloc(grpc_pollset_size());
120 grpc_pollset_init(args->pollset, &args->mu);
121 args->pollset_set = grpc_pollset_set_create();
122 grpc_pollset_set_add_pollset(args->pollset_set, args->pollset);
123 args->lock = grpc_combiner_create();
124 gpr_atm_rel_store(&args->done_atm, 0);
125 args->channel_args = nullptr;
126 }
127
DoNothing(void * arg,grpc_error * error)128 void DoNothing(void* arg, grpc_error* error) {}
129
ArgsFinish(ArgsStruct * args)130 void ArgsFinish(ArgsStruct* args) {
131 grpc_pollset_set_del_pollset(args->pollset_set, args->pollset);
132 grpc_pollset_set_destroy(args->pollset_set);
133 grpc_closure DoNothing_cb;
134 GRPC_CLOSURE_INIT(&DoNothing_cb, DoNothing, nullptr,
135 grpc_schedule_on_exec_ctx);
136 grpc_pollset_shutdown(args->pollset, &DoNothing_cb);
137 // exec_ctx needs to be flushed before calling grpc_pollset_destroy()
138 grpc_channel_args_destroy(args->channel_args);
139 grpc_core::ExecCtx::Get()->Flush();
140 grpc_pollset_destroy(args->pollset);
141 gpr_free(args->pollset);
142 GRPC_COMBINER_UNREF(args->lock, nullptr);
143 }
144
PollPollsetUntilRequestDone(ArgsStruct * args)145 void PollPollsetUntilRequestDone(ArgsStruct* args) {
146 while (true) {
147 bool done = gpr_atm_acq_load(&args->done_atm) != 0;
148 if (done) {
149 break;
150 }
151 grpc_pollset_worker* worker = nullptr;
152 grpc_core::ExecCtx exec_ctx;
153 gpr_mu_lock(args->mu);
154 GRPC_LOG_IF_ERROR(
155 "pollset_work",
156 grpc_pollset_work(args->pollset, &worker,
157 grpc_timespec_to_millis_round_up(
158 gpr_inf_future(GPR_CLOCK_REALTIME))));
159 gpr_mu_unlock(args->mu);
160 }
161 }
162
CheckResolverResultAssertFailureLocked(void * arg,grpc_error * error)163 void CheckResolverResultAssertFailureLocked(void* arg, grpc_error* error) {
164 EXPECT_NE(error, GRPC_ERROR_NONE);
165 ArgsStruct* args = static_cast<ArgsStruct*>(arg);
166 gpr_atm_rel_store(&args->done_atm, 1);
167 gpr_mu_lock(args->mu);
168 GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr));
169 gpr_mu_unlock(args->mu);
170 }
171
TestCancelActiveDNSQuery(ArgsStruct * args)172 void TestCancelActiveDNSQuery(ArgsStruct* args) {
173 int fake_dns_port = grpc_pick_unused_port_or_die();
174 FakeNonResponsiveDNSServer fake_dns_server(fake_dns_port);
175 char* client_target;
176 GPR_ASSERT(gpr_asprintf(
177 &client_target,
178 "dns://[::1]:%d/dont-care-since-wont-be-resolved.test.com:1234",
179 fake_dns_port));
180 // create resolver and resolve
181 grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
182 grpc_core::ResolverRegistry::CreateResolver(
183 client_target, nullptr, args->pollset_set, args->lock);
184 gpr_free(client_target);
185 grpc_closure on_resolver_result_changed;
186 GRPC_CLOSURE_INIT(&on_resolver_result_changed,
187 CheckResolverResultAssertFailureLocked, (void*)args,
188 grpc_combiner_scheduler(args->lock));
189 resolver->NextLocked(&args->channel_args, &on_resolver_result_changed);
190 // Without resetting and causing resolver shutdown, the
191 // PollPollsetUntilRequestDone call should never finish.
192 resolver.reset();
193 grpc_core::ExecCtx::Get()->Flush();
194 PollPollsetUntilRequestDone(args);
195 ArgsFinish(args);
196 }
197
TEST(CancelDuringAresQuery,TestCancelActiveDNSQuery)198 TEST(CancelDuringAresQuery, TestCancelActiveDNSQuery) {
199 grpc_core::ExecCtx exec_ctx;
200 ArgsStruct args;
201 ArgsInit(&args);
202 TestCancelActiveDNSQuery(&args);
203 }
204
205 #ifdef GPR_WINDOWS
206
MaybePollArbitraryPollsetTwice()207 void MaybePollArbitraryPollsetTwice() {
208 grpc_pollset* pollset = (grpc_pollset*)gpr_zalloc(grpc_pollset_size());
209 gpr_mu* mu;
210 grpc_pollset_init(pollset, &mu);
211 grpc_pollset_worker* worker = nullptr;
212 // Make a zero timeout poll
213 gpr_mu_lock(mu);
214 GRPC_LOG_IF_ERROR(
215 "pollset_work",
216 grpc_pollset_work(pollset, &worker, grpc_core::ExecCtx::Get()->Now()));
217 gpr_mu_unlock(mu);
218 grpc_core::ExecCtx::Get()->Flush();
219 // Make a second zero-timeout poll (in case the first one
220 // short-circuited by picking up a previous "kick")
221 gpr_mu_lock(mu);
222 GRPC_LOG_IF_ERROR(
223 "pollset_work",
224 grpc_pollset_work(pollset, &worker, grpc_core::ExecCtx::Get()->Now()));
225 gpr_mu_unlock(mu);
226 grpc_core::ExecCtx::Get()->Flush();
227 grpc_pollset_destroy(pollset);
228 gpr_free(pollset);
229 }
230
231 #else
232
MaybePollArbitraryPollsetTwice()233 void MaybePollArbitraryPollsetTwice() {}
234
235 #endif
236
TEST(CancelDuringAresQuery,TestFdsAreDeletedFromPollsetSet)237 TEST(CancelDuringAresQuery, TestFdsAreDeletedFromPollsetSet) {
238 grpc_core::ExecCtx exec_ctx;
239 ArgsStruct args;
240 ArgsInit(&args);
241 // Add fake_other_pollset_set into the mix to test
242 // that we're explicitly deleting fd's from their pollset.
243 // If we aren't doing so, then the remaining presence of
244 // "fake_other_pollset_set" after the request is done and the resolver
245 // pollset set is destroyed should keep the resolver's fd alive and
246 // fail the test.
247 grpc_pollset_set* fake_other_pollset_set = grpc_pollset_set_create();
248 grpc_pollset_set_add_pollset_set(fake_other_pollset_set, args.pollset_set);
249 // Note that running the cancellation c-ares test is somewhat irrelevant for
250 // this test. This test only cares about what happens to fd's that c-ares
251 // opens.
252 TestCancelActiveDNSQuery(&args);
253 // This test relies on the assumption that cancelling a c-ares query
254 // will flush out all callbacks on the current exec ctx, which is true
255 // on posix platforms but not on Windows, because fd shutdown on Windows
256 // requires a trip through the polling loop to schedule the callback.
257 // So we need to do extra polling work on Windows to free things up.
258 MaybePollArbitraryPollsetTwice();
259 EXPECT_EQ(grpc_iomgr_count_objects_for_testing(), 0u);
260 grpc_pollset_set_destroy(fake_other_pollset_set);
261 }
262
TEST(CancelDuringAresQuery,TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful)263 TEST(CancelDuringAresQuery,
264 TestHitDeadlineAndDestroyChannelDuringAresResolutionIsGraceful) {
265 // Start up fake non responsive DNS server
266 int fake_dns_port = grpc_pick_unused_port_or_die();
267 FakeNonResponsiveDNSServer fake_dns_server(fake_dns_port);
268 // Create a call that will try to use the fake DNS server
269 char* client_target = nullptr;
270 GPR_ASSERT(gpr_asprintf(
271 &client_target,
272 "dns://[::1]:%d/dont-care-since-wont-be-resolved.test.com:1234",
273 fake_dns_port));
274 grpc_channel* client =
275 grpc_insecure_channel_create(client_target,
276 /* client_args */ nullptr, nullptr);
277 gpr_free(client_target);
278 grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr);
279 cq_verifier* cqv = cq_verifier_create(cq);
280 gpr_timespec deadline = grpc_timeout_milliseconds_to_deadline(10);
281 grpc_call* call = grpc_channel_create_call(
282 client, nullptr, GRPC_PROPAGATE_DEFAULTS, cq,
283 grpc_slice_from_static_string("/foo"), nullptr, deadline, nullptr);
284 GPR_ASSERT(call);
285 grpc_metadata_array initial_metadata_recv;
286 grpc_metadata_array trailing_metadata_recv;
287 grpc_metadata_array request_metadata_recv;
288 grpc_metadata_array_init(&initial_metadata_recv);
289 grpc_metadata_array_init(&trailing_metadata_recv);
290 grpc_metadata_array_init(&request_metadata_recv);
291 grpc_call_details call_details;
292 grpc_call_details_init(&call_details);
293 grpc_status_code status;
294 const char* error_string;
295 grpc_slice details;
296 // Set ops for client the request
297 grpc_op ops_base[6];
298 memset(ops_base, 0, sizeof(ops_base));
299 grpc_op* op = ops_base;
300 op->op = GRPC_OP_SEND_INITIAL_METADATA;
301 op->data.send_initial_metadata.count = 0;
302 op->flags = 0;
303 op->reserved = nullptr;
304 op++;
305 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
306 op->flags = 0;
307 op->reserved = nullptr;
308 op++;
309 op->op = GRPC_OP_RECV_INITIAL_METADATA;
310 op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
311 op->flags = 0;
312 op->reserved = nullptr;
313 op++;
314 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
315 op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
316 op->data.recv_status_on_client.status = &status;
317 op->data.recv_status_on_client.status_details = &details;
318 op->data.recv_status_on_client.error_string = &error_string;
319 op->flags = 0;
320 op->reserved = nullptr;
321 op++;
322 // Run the call and sanity check it failed as expected
323 grpc_call_error error = grpc_call_start_batch(
324 call, ops_base, static_cast<size_t>(op - ops_base), Tag(1), nullptr);
325 EXPECT_EQ(GRPC_CALL_OK, error);
326 CQ_EXPECT_COMPLETION(cqv, Tag(1), 1);
327 cq_verify(cqv);
328 EXPECT_EQ(status, GRPC_STATUS_DEADLINE_EXCEEDED);
329 // Teardown
330 grpc_slice_unref(details);
331 gpr_free((void*)error_string);
332 grpc_metadata_array_destroy(&initial_metadata_recv);
333 grpc_metadata_array_destroy(&trailing_metadata_recv);
334 grpc_metadata_array_destroy(&request_metadata_recv);
335 grpc_call_details_destroy(&call_details);
336 grpc_call_unref(call);
337 cq_verifier_destroy(cqv);
338 EndTest(client, cq);
339 }
340
341 } // namespace
342
main(int argc,char ** argv)343 int main(int argc, char** argv) {
344 grpc_test_init(argc, argv);
345 ::testing::InitGoogleTest(&argc, argv);
346 gpr_setenv("GRPC_DNS_RESOLVER", "ares");
347 // Sanity check the time that it takes to run the test
348 // including the teardown time (the teardown
349 // part of the test involves cancelling the DNS query,
350 // which is the main point of interest for this test).
351 gpr_timespec overall_deadline = grpc_timeout_seconds_to_deadline(4);
352 grpc_init();
353 auto result = RUN_ALL_TESTS();
354 grpc_shutdown();
355 if (gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), overall_deadline) > 0) {
356 gpr_log(GPR_ERROR, "Test took too long");
357 abort();
358 }
359 return result;
360 }
361