Change cancellation semantics in the iomgr DNSResolver (#29581)

DNS requests were previously cancellable, but it was assumed
that the resolution callback would be called in all cases. Now, requests
provide a `bool Cancel(TaskHandle handle)` method that lets callers know
whether cancellation is successful, and if so, the callback will not be
run.

This is in accordance with EventEngine's cancellation semantics, and it
is a step towards migration from iomgr to EventEngine.
pull/29631/head^2
AJ Heller 3 years ago committed by GitHub
parent 7b53ceec4d
commit 0a21ecdff6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      BUILD
  2. 12
      CMakeLists.txt
  3. 5
      build_autogenerated.yaml
  4. 3
      gRPC-C++.podspec
  5. 3
      gRPC-Core.podspec
  6. 2
      grpc.gemspec
  7. 2
      grpc.gyp
  8. 2
      package.xml
  9. 118
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
  10. 9
      src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
  11. 56
      src/core/lib/event_engine/handle_containers.h
  12. 33
      src/core/lib/http/httpcli.cc
  13. 3
      src/core/lib/http/httpcli.h
  14. 2
      src/core/lib/iomgr/event_engine/resolver.h
  15. 8
      src/core/lib/iomgr/resolve_address.cc
  16. 33
      src/core/lib/iomgr/resolve_address.h
  17. 5
      src/core/lib/iomgr/resolve_address_impl.h
  18. 22
      src/core/lib/iomgr/resolve_address_posix.cc
  19. 5
      src/core/lib/iomgr/resolve_address_posix.h
  20. 21
      src/core/lib/iomgr/resolve_address_windows.cc
  21. 5
      src/core/lib/iomgr/resolve_address_windows.h
  22. 5
      test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
  23. 21
      test/core/end2end/fuzzers/api_fuzzer.cc
  24. 56
      test/core/end2end/goaway_server_test.cc
  25. 3
      test/core/iomgr/resolve_address_posix_test.cc
  26. 62
      test/core/iomgr/resolve_address_test.cc
  27. 1
      tools/doxygen/Doxyfile.c++.internal
  28. 1
      tools/doxygen/Doxyfile.core.internal

10
BUILD

@ -1841,6 +1841,12 @@ grpc_cc_library(
srcs = [
"src/core/lib/event_engine/resolved_address.cc",
],
hdrs = [
"src/core/lib/event_engine/handle_containers.h",
],
external_deps = [
"absl/container:flat_hash_set",
],
deps = [
"event_engine_base_hdrs",
"gpr_base",
@ -3765,13 +3771,14 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h",
],
external_deps = [
"absl/container:flat_hash_set",
"absl/container:inlined_vector",
"absl/base:core_headers",
"absl/memory",
"absl/status",
"absl/status:statusor",
"absl/strings",
"absl/strings:str_format",
"absl/container:inlined_vector",
"address_sorting",
"cares",
],
@ -3780,6 +3787,7 @@ grpc_cc_library(
"config",
"debug_location",
"error",
"event_engine_common",
"gpr_base",
"grpc_base",
"grpc_client_channel",

12
CMakeLists.txt generated

@ -132,6 +132,7 @@ set(gRPC_ABSL_USED_TARGETS
absl_fast_type_id
absl_fixed_array
absl_flat_hash_map
absl_flat_hash_set
absl_function_ref
absl_graphcycles_internal
absl_hash
@ -2305,6 +2306,7 @@ target_link_libraries(grpc
${_gRPC_UPB_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::flat_hash_map
absl::flat_hash_set
absl::inlined_vector
absl::bind_front
absl::hash
@ -2850,6 +2852,7 @@ target_link_libraries(grpc_unsecure
${_gRPC_UPB_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::flat_hash_map
absl::flat_hash_set
absl::inlined_vector
absl::bind_front
absl::hash
@ -8431,7 +8434,6 @@ target_include_directories(cel_authorization_engine_test
target_link_libraries(cel_authorization_engine_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
absl::flat_hash_set
grpc_test_util
)
@ -19147,7 +19149,7 @@ generate_pkgconfig(
"gRPC"
"high performance general RPC framework"
"${gRPC_CORE_VERSION}"
"gpr openssl absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
"gpr openssl absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
"-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz"
""
"grpc.pc")
@ -19157,7 +19159,7 @@ generate_pkgconfig(
"gRPC unsecure"
"high performance general RPC framework without SSL"
"${gRPC_CORE_VERSION}"
"gpr absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
"gpr absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
"-lgrpc_unsecure"
""
"grpc_unsecure.pc")
@ -19167,7 +19169,7 @@ generate_pkgconfig(
"gRPC++"
"C++ wrapper for gRPC"
"${gRPC_CPP_VERSION}"
"grpc absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
"grpc absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
"-lgrpc++"
""
"grpc++.pc")
@ -19177,7 +19179,7 @@ generate_pkgconfig(
"gRPC++ unsecure"
"C++ wrapper for gRPC without SSL"
"${gRPC_CPP_VERSION}"
"grpc_unsecure absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
"grpc_unsecure absl_base absl_bind_front absl_cord absl_core_headers absl_flat_hash_map absl_flat_hash_set absl_hash absl_inlined_vector absl_memory absl_optional absl_random_random absl_span absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time absl_type_traits absl_utility absl_variant"
"-lgrpc++_unsecure"
""
"grpc++_unsecure.pc")

@ -728,6 +728,7 @@ libs:
- src/core/lib/debug/trace.h
- src/core/lib/event_engine/channel_args_endpoint_config.h
- src/core/lib/event_engine/event_engine_factory.h
- src/core/lib/event_engine/handle_containers.h
- src/core/lib/event_engine/sockaddr.h
- src/core/lib/gprpp/atomic_utils.h
- src/core/lib/gprpp/bitset.h
@ -1643,6 +1644,7 @@ libs:
- src/core/tsi/transport_security_grpc.cc
deps:
- absl/container:flat_hash_map
- absl/container:flat_hash_set
- absl/container:inlined_vector
- absl/functional:bind_front
- absl/hash:hash
@ -1913,6 +1915,7 @@ libs:
- src/core/lib/debug/trace.h
- src/core/lib/event_engine/channel_args_endpoint_config.h
- src/core/lib/event_engine/event_engine_factory.h
- src/core/lib/event_engine/handle_containers.h
- src/core/lib/event_engine/sockaddr.h
- src/core/lib/gprpp/atomic_utils.h
- src/core/lib/gprpp/bitset.h
@ -2417,6 +2420,7 @@ libs:
- src/core/tsi/transport_security_grpc.cc
deps:
- absl/container:flat_hash_map
- absl/container:flat_hash_set
- absl/container:inlined_vector
- absl/functional:bind_front
- absl/hash:hash
@ -4830,7 +4834,6 @@ targets:
- src/core/lib/security/authorization/cel_authorization_engine.cc
- test/core/security/cel_authorization_engine_test.cc
deps:
- absl/container:flat_hash_set
- grpc_test_util
- name: certificate_provider_registry_test
gtest: true

3
gRPC-C++.podspec generated

@ -198,6 +198,7 @@ Pod::Spec.new do |s|
ss.dependency 'abseil/base/base', abseil_version
ss.dependency 'abseil/base/core_headers', abseil_version
ss.dependency 'abseil/container/flat_hash_map', abseil_version
ss.dependency 'abseil/container/flat_hash_set', abseil_version
ss.dependency 'abseil/container/inlined_vector', abseil_version
ss.dependency 'abseil/functional/bind_front', abseil_version
ss.dependency 'abseil/hash/hash', abseil_version
@ -669,6 +670,7 @@ Pod::Spec.new do |s|
'src/core/lib/debug/trace.h',
'src/core/lib/event_engine/channel_args_endpoint_config.h',
'src/core/lib/event_engine/event_engine_factory.h',
'src/core/lib/event_engine/handle_containers.h',
'src/core/lib/event_engine/sockaddr.h',
'src/core/lib/gpr/alloc.h',
'src/core/lib/gpr/env.h',
@ -1484,6 +1486,7 @@ Pod::Spec.new do |s|
'src/core/lib/debug/trace.h',
'src/core/lib/event_engine/channel_args_endpoint_config.h',
'src/core/lib/event_engine/event_engine_factory.h',
'src/core/lib/event_engine/handle_containers.h',
'src/core/lib/event_engine/sockaddr.h',
'src/core/lib/gpr/alloc.h',
'src/core/lib/gpr/env.h',

3
gRPC-Core.podspec generated

@ -174,6 +174,7 @@ Pod::Spec.new do |s|
ss.dependency 'abseil/base/base', abseil_version
ss.dependency 'abseil/base/core_headers', abseil_version
ss.dependency 'abseil/container/flat_hash_map', abseil_version
ss.dependency 'abseil/container/flat_hash_set', abseil_version
ss.dependency 'abseil/container/inlined_vector', abseil_version
ss.dependency 'abseil/functional/bind_front', abseil_version
ss.dependency 'abseil/hash/hash', abseil_version
@ -1034,6 +1035,7 @@ Pod::Spec.new do |s|
'src/core/lib/event_engine/default_event_engine_factory.cc',
'src/core/lib/event_engine/event_engine.cc',
'src/core/lib/event_engine/event_engine_factory.h',
'src/core/lib/event_engine/handle_containers.h',
'src/core/lib/event_engine/memory_allocator.cc',
'src/core/lib/event_engine/resolved_address.cc',
'src/core/lib/event_engine/sockaddr.cc',
@ -2088,6 +2090,7 @@ Pod::Spec.new do |s|
'src/core/lib/debug/trace.h',
'src/core/lib/event_engine/channel_args_endpoint_config.h',
'src/core/lib/event_engine/event_engine_factory.h',
'src/core/lib/event_engine/handle_containers.h',
'src/core/lib/event_engine/sockaddr.h',
'src/core/lib/gpr/alloc.h',
'src/core/lib/gpr/env.h',

2
grpc.gemspec generated

@ -949,6 +949,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/event_engine/default_event_engine_factory.cc )
s.files += %w( src/core/lib/event_engine/event_engine.cc )
s.files += %w( src/core/lib/event_engine/event_engine_factory.h )
s.files += %w( src/core/lib/event_engine/handle_containers.h )
s.files += %w( src/core/lib/event_engine/memory_allocator.cc )
s.files += %w( src/core/lib/event_engine/resolved_address.cc )
s.files += %w( src/core/lib/event_engine/sockaddr.cc )
@ -1562,6 +1563,7 @@ Gem::Specification.new do |s|
s.files += %w( third_party/abseil-cpp/absl/base/thread_annotations.h )
s.files += %w( third_party/abseil-cpp/absl/container/fixed_array.h )
s.files += %w( third_party/abseil-cpp/absl/container/flat_hash_map.h )
s.files += %w( third_party/abseil-cpp/absl/container/flat_hash_set.h )
s.files += %w( third_party/abseil-cpp/absl/container/inlined_vector.h )
s.files += %w( third_party/abseil-cpp/absl/container/internal/common.h )
s.files += %w( third_party/abseil-cpp/absl/container/internal/compressed_tuple.h )

2
grpc.gyp generated

@ -361,6 +361,7 @@
'type': 'static_library',
'dependencies': [
'absl/container:flat_hash_map',
'absl/container:flat_hash_set',
'absl/container:inlined_vector',
'absl/functional:bind_front',
'absl/hash:hash',
@ -1113,6 +1114,7 @@
'type': 'static_library',
'dependencies': [
'absl/container:flat_hash_map',
'absl/container:flat_hash_set',
'absl/container:inlined_vector',
'absl/functional:bind_front',
'absl/hash:hash',

2
package.xml generated

@ -931,6 +931,7 @@
<file baseinstalldir="/" name="src/core/lib/event_engine/default_event_engine_factory.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/event_engine.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/event_engine_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/handle_containers.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/memory_allocator.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/resolved_address.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/event_engine/sockaddr.cc" role="src" />
@ -1566,6 +1567,7 @@
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/base/thread_annotations.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/fixed_array.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/flat_hash_map.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/flat_hash_set.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/inlined_vector.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/internal/common.h" role="src" />
<file baseinstalldir="/" name="third_party/abseil-cpp/absl/container/internal/compressed_tuple.h" role="src" />

@ -16,6 +16,7 @@
#include <grpc/support/port_platform.h>
#include <stdint.h>
#include <stdlib.h>
#include <algorithm>
@ -34,6 +35,7 @@
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include <grpc/event_engine/event_engine.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -64,6 +66,7 @@
#include <address_sorting/address_sorting.h>
#include "absl/container/flat_hash_set.h"
#include "absl/container/inlined_vector.h"
#include "absl/strings/str_cat.h"
@ -73,6 +76,7 @@
#include "src/core/ext/filters/client_channel/resolver/polling_resolver.h"
#include "src/core/lib/backoff/backoff.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/event_engine/handle_containers.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/iomgr/gethostname.h"
#include "src/core/lib/iomgr/resolve_address.h"
@ -358,74 +362,83 @@ class AresClientChannelDNSResolverFactory : public ResolverFactory {
class AresDNSResolver : public DNSResolver {
public:
class AresRequest : public DNSResolver::Request {
class AresRequest {
public:
AresRequest(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* interested_parties,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_resolve_address_done)
on_resolve_address_done,
AresDNSResolver* resolver, intptr_t aba_token)
: name_(std::string(name)),
default_port_(std::string(default_port)),
interested_parties_(interested_parties),
on_resolve_address_done_(std::move(on_resolve_address_done)) {
on_resolve_address_done_(std::move(on_resolve_address_done)),
completed_(false),
resolver_(resolver),
aba_token_(aba_token) {
GRPC_CARES_TRACE_LOG("AresRequest:%p ctor", this);
GRPC_CLOSURE_INIT(&on_dns_lookup_done_, OnDnsLookupDone, this,
grpc_schedule_on_exec_ctx);
}
~AresRequest() override {
GRPC_CARES_TRACE_LOG("AresRequest:%p dtor ares_request_:%p", this,
ares_request_.get());
}
void Start() override {
MutexLock lock(&mu_);
Ref().release(); // ref held by resolution
ares_request_ = std::unique_ptr<grpc_ares_request>(grpc_dns_lookup_ares(
"" /* dns_server */, name_.c_str(), default_port_.c_str(),
/*dns_server=*/"", name_.c_str(), default_port_.c_str(),
interested_parties_, &on_dns_lookup_done_, &addresses_,
nullptr /* balancer_addresses */, nullptr /* service_config_json */,
/*balancer_addresses=*/nullptr, /*service_config_json=*/nullptr,
GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS));
GRPC_CARES_TRACE_LOG("AresRequest:%p Start ares_request_:%p", this,
ares_request_.get());
}
void Orphan() override {
{
~AresRequest() {
GRPC_CARES_TRACE_LOG("AresRequest:%p dtor ares_request_:%p", this,
ares_request_.get());
resolver_->UnregisterRequest(task_handle());
}
bool Cancel() {
MutexLock lock(&mu_);
GRPC_CARES_TRACE_LOG("AresRequest:%p Orphan ares_request_:%p", this,
GRPC_CARES_TRACE_LOG("AresRequest:%p Cancel ares_request_:%p", this,
ares_request_.get());
if (ares_request_ != nullptr) {
// Cancelling the same lookup twice is a bug.
if (completed_) return false;
// OnDnsLookupDone will still be run
grpc_cancel_ares_request(ares_request_.get());
completed_ = true;
return true;
}
}
Unref();
TaskHandle task_handle() {
return {reinterpret_cast<intptr_t>(this), aba_token_};
}
private:
// Called by ares when lookup has completed or when cancelled. It is always
// called exactly once.
static void OnDnsLookupDone(void* arg, grpc_error_handle error) {
AresRequest* r = static_cast<AresRequest*>(arg);
AresRequest* request = static_cast<AresRequest*>(arg);
GRPC_CARES_TRACE_LOG("AresRequest:%p OnDnsLookupDone", request);
// This request is deleted and unregistered upon any exit.
std::unique_ptr<AresRequest> deleter(request);
std::vector<grpc_resolved_address> resolved_addresses;
{
MutexLock lock(&r->mu_);
GRPC_CARES_TRACE_LOG("AresRequest:%p OnDnsLookupDone error:%s", r,
grpc_error_std_string(error).c_str());
if (r->addresses_ != nullptr) {
resolved_addresses.reserve(r->addresses_->size());
for (const auto& server_address : *r->addresses_) {
MutexLock lock(&request->mu_);
if (request->completed_) {
return;
}
request->completed_ = true;
if (request->addresses_ != nullptr) {
resolved_addresses.reserve(request->addresses_->size());
for (const auto& server_address : *request->addresses_) {
resolved_addresses.push_back(server_address.address());
}
}
}
if (error == GRPC_ERROR_NONE) {
// it's safe to run this inline since we've already been scheduled
// on the ExecCtx
r->on_resolve_address_done_(std::move(resolved_addresses));
} else {
r->on_resolve_address_done_(grpc_error_to_absl_status(error));
if (error != GRPC_ERROR_NONE) {
request->on_resolve_address_done_(grpc_error_to_absl_status(error));
return;
}
r->Unref();
request->on_resolve_address_done_(std::move(resolved_addresses));
}
// mutex to synchronize access to this object (but not to the ares_request
@ -449,6 +462,12 @@ class AresDNSResolver : public DNSResolver {
grpc_closure on_dns_lookup_done_ ABSL_GUARDED_BY(mu_);
// underlying ares_request that the query is performed on
std::unique_ptr<grpc_ares_request> ares_request_ ABSL_GUARDED_BY(mu_);
bool completed_ ABSL_GUARDED_BY(mu_);
// Parent resolver that created this request
AresDNSResolver* resolver_;
// Unique token to help distinguish this request from others that may later
// be created in the same memory location.
intptr_t aba_token_;
};
// gets the singleton instance, possibly creating it first
@ -457,13 +476,17 @@ class AresDNSResolver : public DNSResolver {
return instance;
}
OrphanablePtr<DNSResolver::Request> ResolveName(
TaskHandle ResolveName(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* interested_parties,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done) override {
return MakeOrphanable<AresRequest>(name, default_port, interested_parties,
std::move(on_done));
MutexLock lock(&mu_);
auto* request = new AresRequest(name, default_port, interested_parties,
std::move(on_done), this, aba_token_++);
auto handle = request->task_handle();
open_requests_.insert(handle);
return handle;
}
absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking(
@ -473,9 +496,30 @@ class AresDNSResolver : public DNSResolver {
return default_resolver_->ResolveNameBlocking(name, default_port);
}
bool Cancel(TaskHandle handle) override {
MutexLock lock(&mu_);
if (!open_requests_.contains(handle)) {
// Unknown request, possibly completed already, or an invalid handle.
return false;
}
auto* request = reinterpret_cast<AresRequest*>(handle.keys[0]);
GRPC_CARES_TRACE_LOG("AresDNSResolver:%p cancel ares_request:%p", this,
request);
return request->Cancel();
}
private:
// Called exclusively from the AresRequest destructor.
void UnregisterRequest(TaskHandle handle) {
MutexLock lock(&mu_);
open_requests_.erase(handle);
}
// the previous default DNS resolver, used to delegate blocking DNS calls to
DNSResolver* default_resolver_ = GetDNSResolver();
Mutex mu_;
LookupTaskHandleSet open_requests_ ABSL_GUARDED_BY(mu_);
intptr_t aba_token_ ABSL_GUARDED_BY(mu_) = 0;
};
bool ShouldUseAres(const char* resolver_env) {

@ -108,16 +108,15 @@ NativeClientChannelDNSResolver::~NativeClientChannelDNSResolver() {
OrphanablePtr<Orphanable> NativeClientChannelDNSResolver::StartRequest() {
Ref(DEBUG_LOCATION, "dns_request").release();
auto dns_request = GetDNSResolver()->ResolveName(
auto dns_request_handle = GetDNSResolver()->ResolveName(
name_to_resolve(), kDefaultSecurePort, interested_parties(),
absl::bind_front(&NativeClientChannelDNSResolver::OnResolved, this));
if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_dns_resolver)) {
gpr_log(GPR_DEBUG, "[dns_resolver=%p] starting request=%p", this,
dns_request.get());
DNSResolver::HandleToString(dns_request_handle).c_str());
}
dns_request->Start();
// Explicit type conversion to work around issue with older compilers.
return OrphanablePtr<Orphanable>(dns_request.release());
// Not cancellable.
return nullptr;
}
void NativeClientChannelDNSResolver::OnResolved(

@ -0,0 +1,56 @@
// Copyright 2022 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef GRPC_CORE_LIB_EVENT_ENGINE_HANDLE_CONTAINERS_H
#define GRPC_CORE_LIB_EVENT_ENGINE_HANDLE_CONTAINERS_H
#include <grpc/support/port_platform.h>
#include "absl/container/flat_hash_set.h"
#include "absl/hash/hash.h"
#include <grpc/event_engine/event_engine.h>
// Used for heterogenous lookup of TaskHandles in abseil containers.
template <typename TaskHandle>
struct TaskHandleComparator {
struct Hash {
using HashType = std::pair<const intptr_t, const intptr_t>;
using is_transparent = void;
size_t operator()(const TaskHandle& handle) const {
return absl::Hash<HashType>()({handle.keys[0], handle.keys[1]});
}
};
struct Eq {
using is_transparent = void;
bool operator()(const TaskHandle& lhs, const TaskHandle& rhs) const {
return lhs.keys[0] == rhs.keys[0] && lhs.keys[1] == rhs.keys[1];
}
};
};
using TaskHandleSet = absl::flat_hash_set<
grpc_event_engine::experimental::EventEngine::TaskHandle,
TaskHandleComparator<
grpc_event_engine::experimental::EventEngine::TaskHandle>::Hash,
TaskHandleComparator<
grpc_event_engine::experimental::EventEngine::TaskHandle>::Eq>;
using LookupTaskHandleSet = absl::flat_hash_set<
grpc_event_engine::experimental::EventEngine::DNSResolver::LookupTaskHandle,
TaskHandleComparator<grpc_event_engine::experimental::EventEngine::
DNSResolver::LookupTaskHandle>::Hash,
TaskHandleComparator<grpc_event_engine::experimental::EventEngine::
DNSResolver::LookupTaskHandle>::Eq>;
#endif // GRPC_CORE_LIB_EVENT_ENGINE_HANDLE_CONTAINERS_H

@ -179,10 +179,6 @@ HttpRequest::HttpRequest(
grpc_schedule_on_exec_ctx);
GPR_ASSERT(pollent);
grpc_polling_entity_add_to_pollset_set(pollent, pollset_set_);
// Create the DNS resolver. We'll start resolving when Start is called.
dns_request_ = GetDNSResolver()->ResolveName(
uri_.authority(), uri_.scheme(), pollset_set_,
absl::bind_front(&HttpRequest::OnResolved, this));
}
HttpRequest::~HttpRequest() {
@ -206,7 +202,9 @@ void HttpRequest::Start() {
return;
}
Ref().release(); // ref held by pending DNS resolution
dns_request_->Start();
dns_request_handle_ = GetDNSResolver()->ResolveName(
uri_.authority(), uri_.scheme(), pollset_set_,
absl::bind_front(&HttpRequest::OnResolved, this));
}
void HttpRequest::Orphan() {
@ -214,14 +212,13 @@ void HttpRequest::Orphan() {
MutexLock lock(&mu_);
GPR_ASSERT(!cancelled_);
cancelled_ = true;
dns_request_.reset(); // cancel potentially pending DNS resolution
if (connecting_) {
// gRPC's TCP connection establishment API doesn't currently have
// a mechanism for cancellation. So invoke the user callback now. The TCP
// connection will eventually complete (at least within its deadline), and
// we'll simply unref ourselves at that point.
// TODO(apolcyn): fix this to cancel the TCP connection attempt when
// an API to do so exists.
// cancel potentially pending DNS resolution.
if (dns_request_handle_.has_value() &&
GetDNSResolver()->Cancel(dns_request_handle_.value())) {
Finish(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"cancelled during DNS resolution"));
Unref();
} else if (connecting_) {
Finish(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"HTTP request cancelled during TCP connection establishment",
&overall_error_, 1));
@ -410,16 +407,16 @@ void HttpRequest::OnResolved(
absl::StatusOr<std::vector<grpc_resolved_address>> addresses_or) {
RefCountedPtr<HttpRequest> unreffer(this);
MutexLock lock(&mu_);
dns_request_.reset();
if (!addresses_or.ok()) {
Finish(absl_status_to_grpc_error(addresses_or.status()));
return;
}
dns_request_handle_.reset();
if (cancelled_) {
Finish(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"cancelled during DNS resolution"));
return;
}
if (!addresses_or.ok()) {
Finish(absl_status_to_grpc_error(addresses_or.status()));
return;
}
addresses_ = std::move(*addresses_or);
next_address_ = 0;
NextAddress(GRPC_ERROR_NONE);

@ -247,7 +247,8 @@ class HttpRequest : public InternallyRefCounted<HttpRequest> {
grpc_slice_buffer incoming_ ABSL_GUARDED_BY(mu_);
grpc_slice_buffer outgoing_ ABSL_GUARDED_BY(mu_);
grpc_error_handle overall_error_ ABSL_GUARDED_BY(mu_) = GRPC_ERROR_NONE;
OrphanablePtr<DNSResolver::Request> dns_request_ ABSL_GUARDED_BY(mu_);
absl::optional<DNSResolver::TaskHandle> dns_request_handle_
ABSL_GUARDED_BY(mu_) = DNSResolver::kNullHandle;
};
} // namespace grpc_core

@ -35,6 +35,7 @@
namespace grpc_core {
namespace experimental {
#ifdef GRPC_USE_EVENT_ENGINE
class EventEngineDNSResolver : public DNSResolver {
public:
// Gets the singleton instance, creating it first if it doesn't exist
@ -49,6 +50,7 @@ class EventEngineDNSResolver : public DNSResolver {
absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking(
absl::string_view name, absl::string_view default_port) override;
};
#endif // GRPC_USE_EVENT_ENGINE
} // namespace experimental
} // namespace grpc_core

@ -19,6 +19,8 @@
#include "src/core/lib/iomgr/resolve_address.h"
#include "absl/strings/str_cat.h"
#include <grpc/event_engine/event_engine.h>
#include <grpc/support/alloc.h>
@ -29,8 +31,14 @@ namespace {
DNSResolver* g_dns_resolver;
}
constexpr DNSResolver::TaskHandle DNSResolver::kNullHandle;
void SetDNSResolver(DNSResolver* resolver) { g_dns_resolver = resolver; }
DNSResolver* GetDNSResolver() { return g_dns_resolver; }
std::string DNSResolver::HandleToString(TaskHandle handle) {
return absl::StrCat("{", handle.keys[0], ",", handle.keys[1], "}");
}
} // namespace grpc_core

@ -25,6 +25,8 @@
#include "absl/status/statusor.h"
#include <grpc/event_engine/event_engine.h>
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/iomgr/pollset_set.h"
#include "src/core/lib/iomgr/port.h"
@ -39,37 +41,40 @@ constexpr int kDefaultSecurePortInt = 443;
// A singleton class used for async and blocking DNS resolution
class DNSResolver {
public:
// Tracks a single asynchronous DNS resolution attempt. The DNS
// resolution should be arranged to be cancelled as soon as possible
// when Orphan is called.
class Request : public InternallyRefCounted<Request> {
public:
// Begins async DNS resolution
virtual void Start() = 0;
};
using TaskHandle = ::grpc_event_engine::experimental::EventEngine::
DNSResolver::LookupTaskHandle;
static constexpr TaskHandle kNullHandle{0, 0};
virtual ~DNSResolver() {}
static std::string HandleToString(TaskHandle handle);
// Asynchronously resolve name. Use \a default_port if a port isn't designated
// in \a name, otherwise use the port in \a name. On completion, \a on_done is
// invoked with the result.
//
// Note for implementations: calls may acquire locks in \a on_done which
// were previously held while calling Request::Start(). Therefore,
// implementations must not invoke \a on_done inline from the call to
// Request::Start(). The DNSCallbackExecCtxScheduler utility may help address
// this.
virtual OrphanablePtr<Request> ResolveName(
// were previously held while starting the request. Therefore,
// implementations must not invoke \a on_done inline from the call site that
// starts the request. The DNSCallbackExecCtxScheduler utility may help
// address this.
virtual TaskHandle ResolveName(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* interested_parties,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done) GRPC_MUST_USE_RESULT = 0;
on_done) = 0;
// Resolve name in a blocking fashion. Use \a default_port if a port isn't
// designated in \a name, otherwise use the port in \a name.
virtual absl::StatusOr<std::vector<grpc_resolved_address>>
ResolveNameBlocking(absl::string_view name,
absl::string_view default_port) = 0;
// This shares the same semantics with \a EventEngine::Cancel: successfully
// cancelled lookups will not have their callbacks executed, and this
// method returns true. If a TaskHandle is unknown, this method should return
// false.
virtual bool Cancel(TaskHandle handle) = 0;
};
// Override the active DNS resolver which should be used for all DNS

@ -26,9 +26,8 @@
namespace grpc_core {
// A fire and forget class used by DNSResolver::Request implementations to
// schedule DNS resolution callbacks on the ExecCtx, which is frequently
// necessary to avoid lock inversion related problems.
// A fire and forget class to schedule DNS resolution callbacks on the ExecCtx,
// which is frequently necessary to avoid lock inversion related problems.
class DNSCallbackExecCtxScheduler {
public:
DNSCallbackExecCtxScheduler(

@ -45,7 +45,7 @@
namespace grpc_core {
namespace {
class NativeDNSRequest : public DNSResolver::Request {
class NativeDNSRequest {
public:
NativeDNSRequest(
absl::string_view name, absl::string_view default_port,
@ -53,18 +53,9 @@ class NativeDNSRequest : public DNSResolver::Request {
on_done)
: name_(name), default_port_(default_port), on_done_(std::move(on_done)) {
GRPC_CLOSURE_INIT(&request_closure_, DoRequestThread, this, nullptr);
}
// Starts the resolution
void Start() override {
Ref().release(); // ref held by callback
Executor::Run(&request_closure_, GRPC_ERROR_NONE, ExecutorType::RESOLVER);
}
// This is a no-op for the native resolver. Note
// that no I/O polling is required for the resolution to finish.
void Orphan() override { Unref(); }
private:
// Callback to be passed to grpc Executor to asynch-ify
// ResolveNameBlocking
@ -74,7 +65,7 @@ class NativeDNSRequest : public DNSResolver::Request {
GetDNSResolver()->ResolveNameBlocking(r->name_, r->default_port_);
// running inline is safe since we've already been scheduled on the executor
r->on_done_(std::move(result));
r->Unref();
delete r;
}
const std::string name_;
@ -91,13 +82,14 @@ NativeDNSResolver* NativeDNSResolver::GetOrCreate() {
return instance;
}
OrphanablePtr<DNSResolver::Request> NativeDNSResolver::ResolveName(
DNSResolver::TaskHandle NativeDNSResolver::ResolveName(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* /* interested_parties */,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done) {
return MakeOrphanable<NativeDNSRequest>(name, default_port,
std::move(on_done));
// self-deleting class
new NativeDNSRequest(name, default_port, std::move(on_done));
return kNullHandle;
}
absl::StatusOr<std::vector<grpc_resolved_address>>
@ -181,6 +173,8 @@ done:
return error_result;
}
bool NativeDNSResolver::Cancel(TaskHandle /*handle*/) { return false; }
} // namespace grpc_core
#endif

@ -32,7 +32,7 @@ class NativeDNSResolver : public DNSResolver {
// Gets the singleton instance, creating it first if it doesn't exist
static NativeDNSResolver* GetOrCreate();
OrphanablePtr<DNSResolver::Request> ResolveName(
TaskHandle ResolveName(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* interested_parties,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
@ -40,6 +40,9 @@ class NativeDNSResolver : public DNSResolver {
absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking(
absl::string_view name, absl::string_view default_port) override;
// NativeDNSResolver does not support cancellation.
bool Cancel(TaskHandle handle) override;
};
} // namespace grpc_core

@ -48,7 +48,7 @@
namespace grpc_core {
namespace {
class NativeDNSRequest : public DNSResolver::Request {
class NativeDNSRequest {
public:
NativeDNSRequest(
absl::string_view name, absl::string_view default_port,
@ -56,18 +56,9 @@ class NativeDNSRequest : public DNSResolver::Request {
on_done)
: name_(name), default_port_(default_port), on_done_(std::move(on_done)) {
GRPC_CLOSURE_INIT(&request_closure_, DoRequestThread, this, nullptr);
}
// Starts the resolution
void Start() override {
Ref().release(); // ref held by callback
Executor::Run(&request_closure_, GRPC_ERROR_NONE, ExecutorType::RESOLVER);
}
// This is a no-op for the native resolver. Note
// that no I/O polling is required for the resolution to finish.
void Orphan() override { Unref(); }
private:
// Callback to be passed to grpc Executor to asynch-ify
// ResolveNameBlocking
@ -77,7 +68,7 @@ class NativeDNSRequest : public DNSResolver::Request {
GetDNSResolver()->ResolveNameBlocking(r->name_, r->default_port_);
// running inline is safe since we've already been scheduled on the executor
r->on_done_(std::move(result));
r->Unref();
delete r;
}
const std::string name_;
@ -94,13 +85,13 @@ NativeDNSResolver* NativeDNSResolver::GetOrCreate() {
return instance;
}
OrphanablePtr<DNSResolver::Request> NativeDNSResolver::ResolveName(
DNSResolver::TaskHandle NativeDNSResolver::ResolveName(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* /* interested_parties */,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done) {
return MakeOrphanable<NativeDNSRequest>(name, default_port,
std::move(on_done));
new NativeDNSRequest(name, default_port, std::move(on_done));
return kNullHandle;
}
absl::StatusOr<std::vector<grpc_resolved_address>>
@ -166,6 +157,8 @@ done:
return error_result;
}
bool NativeDNSResolver::Cancel(TaskHandle /*handle*/) { return false; }
} // namespace grpc_core
#endif

@ -32,7 +32,7 @@ class NativeDNSResolver : public DNSResolver {
// Gets the singleton instance, creating it first if it doesn't exist
static NativeDNSResolver* GetOrCreate();
OrphanablePtr<DNSResolver::Request> ResolveName(
TaskHandle ResolveName(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* interested_parties,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
@ -40,6 +40,9 @@ class NativeDNSResolver : public DNSResolver {
absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking(
absl::string_view name, absl::string_view default_port) override;
// NativeDNSResolver does not support cancellation.
bool Cancel(TaskHandle handle) override;
};
} // namespace grpc_core

@ -66,7 +66,7 @@ class TestDNSResolver : public grpc_core::DNSResolver {
public:
// Wrapper around default resolve_address in order to count the number of
// times we incur in a system-level name resolution.
grpc_core::OrphanablePtr<grpc_core::DNSResolver::Request> ResolveName(
TaskHandle ResolveName(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* interested_parties,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
@ -100,6 +100,9 @@ class TestDNSResolver : public grpc_core::DNSResolver {
absl::string_view name, absl::string_view default_port) override {
return g_default_dns_resolver->ResolveNameBlocking(name, default_port);
}
// Not cancellable
bool Cancel(TaskHandle /*handle*/) override { return false; }
};
} // namespace

@ -114,25 +114,19 @@ namespace {
class FuzzerDNSResolver : public grpc_core::DNSResolver {
public:
class FuzzerDNSRequest : public grpc_core::DNSResolver::Request {
class FuzzerDNSRequest {
public:
FuzzerDNSRequest(
absl::string_view name,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done)
: name_(std::string(name)), on_done_(std::move(on_done)) {}
void Start() override {
Ref().release(); // ref held by timer callback
: name_(std::string(name)), on_done_(std::move(on_done)) {
grpc_timer_init(
&timer_,
grpc_core::Duration::Seconds(1) + grpc_core::ExecCtx::Get()->Now(),
GRPC_CLOSURE_CREATE(FinishResolve, this, grpc_schedule_on_exec_ctx));
}
// cancellation not implemented
void Orphan() override { Unref(); }
private:
static void FinishResolve(void* arg, grpc_error_handle error) {
FuzzerDNSRequest* self = static_cast<FuzzerDNSRequest*>(arg);
@ -145,7 +139,7 @@ class FuzzerDNSResolver : public grpc_core::DNSResolver {
} else {
self->on_done_(absl::UnknownError("Resolution failed"));
}
self->Unref();
delete self;
}
const std::string name_;
@ -161,13 +155,13 @@ class FuzzerDNSResolver : public grpc_core::DNSResolver {
return instance;
}
grpc_core::OrphanablePtr<grpc_core::DNSResolver::Request> ResolveName(
TaskHandle ResolveName(
absl::string_view name, absl::string_view /* default_port */,
grpc_pollset_set* /* interested_parties */,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done) override {
return grpc_core::MakeOrphanable<FuzzerDNSRequest>(name,
std::move(on_done));
new FuzzerDNSRequest(name, std::move(on_done));
return kNullHandle;
}
absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking(
@ -175,6 +169,9 @@ class FuzzerDNSResolver : public grpc_core::DNSResolver {
absl::string_view /* default_port */) override {
GPR_ASSERT(0);
}
// FuzzerDNSResolver does not support cancellation.
bool Cancel(TaskHandle /*handle*/) override { return false; }
};
} // namespace

@ -63,19 +63,35 @@ grpc_core::DNSResolver* g_default_dns_resolver;
class TestDNSResolver : public grpc_core::DNSResolver {
public:
class TestDNSRequest : public grpc_core::DNSResolver::Request {
public:
explicit TestDNSRequest(
TaskHandle ResolveName(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* interested_parties,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done)
: on_done_(std::move(on_done)) {}
on_done) override {
if (name != "test") {
return g_default_dns_resolver->ResolveName(
name, default_port, interested_parties, std::move(on_done));
}
MakeDNSRequest(std::move(on_done));
return kNullHandle;
}
void Start() override {
absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking(
absl::string_view name, absl::string_view default_port) override {
return g_default_dns_resolver->ResolveNameBlocking(name, default_port);
}
bool Cancel(TaskHandle /*handle*/) override { return false; }
private:
void MakeDNSRequest(
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done) {
gpr_mu_lock(&g_mu);
if (g_resolve_port < 0) {
gpr_mu_unlock(&g_mu);
new grpc_core::DNSCallbackExecCtxScheduler(
std::move(on_done_), absl::UnknownError("Forced Failure"));
std::move(on_done), absl::UnknownError("Forced Failure"));
} else {
std::vector<grpc_resolved_address> addrs;
grpc_resolved_address addr;
@ -86,34 +102,10 @@ class TestDNSResolver : public grpc_core::DNSResolver {
addr.len = static_cast<socklen_t>(sizeof(*sa));
addrs.push_back(addr);
gpr_mu_unlock(&g_mu);
new grpc_core::DNSCallbackExecCtxScheduler(std::move(on_done_),
new grpc_core::DNSCallbackExecCtxScheduler(std::move(on_done),
std::move(addrs));
}
}
void Orphan() override { Unref(); }
private:
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done_;
};
grpc_core::OrphanablePtr<grpc_core::DNSResolver::Request> ResolveName(
absl::string_view name, absl::string_view default_port,
grpc_pollset_set* interested_parties,
std::function<void(absl::StatusOr<std::vector<grpc_resolved_address>>)>
on_done) override {
if (name != "test") {
return g_default_dns_resolver->ResolveName(
name, default_port, interested_parties, std::move(on_done));
}
return grpc_core::MakeOrphanable<TestDNSRequest>(std::move(on_done));
}
absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking(
absl::string_view name, absl::string_view default_port) override {
return g_default_dns_resolver->ResolveNameBlocking(name, default_port);
}
};
} // namespace

@ -135,12 +135,11 @@ static void resolve_address_must_succeed(const char* target) {
args_struct args;
args_init(&args);
poll_pollset_until_request_done(&args);
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
target, "1" /* port number */, args.pollset_set,
[&args](absl::StatusOr<std::vector<grpc_resolved_address>> result) {
MustSucceed(&args, std::move(result));
});
r->Start();
grpc_core::ExecCtx::Get()->Flush();
args_finish(&args);
}

@ -154,10 +154,10 @@ class ResolveAddressTest : public ::testing::Test {
Finish();
}
grpc_pollset_set* pollset_set() const { return pollset_set_; }
private:
static void DoNothing(void* /*arg*/, grpc_error_handle /*error*/) {}
void MustNotBeCalled(
absl::StatusOr<std::vector<grpc_resolved_address>> /*result*/) {
FAIL() << "This should never be called";
}
void Finish() {
grpc_core::MutexLockForGprMu lock(mu_);
@ -165,6 +165,11 @@ class ResolveAddressTest : public ::testing::Test {
GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(pollset_, nullptr));
}
grpc_pollset_set* pollset_set() const { return pollset_set_; }
private:
static void DoNothing(void* /*arg*/, grpc_error_handle /*error*/) {}
gpr_mu* mu_;
bool done_ = false; // guarded by mu
grpc_pollset* pollset_; // guarded by mu
@ -178,20 +183,18 @@ class ResolveAddressTest : public ::testing::Test {
TEST_F(ResolveAddressTest, Localhost) {
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
"localhost:1", "", pollset_set(),
absl::bind_front(&ResolveAddressTest::MustSucceed, this));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone();
}
TEST_F(ResolveAddressTest, DefaultPort) {
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
"localhost", "1", pollset_set(),
absl::bind_front(&ResolveAddressTest::MustSucceed, this));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone();
}
@ -201,10 +204,9 @@ TEST_F(ResolveAddressTest, LocalhostResultHasIPv6First) {
GTEST_SKIP() << "this test is only valid with the c-ares resolver";
}
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
"localhost:1", "", pollset_set(),
absl::bind_front(&ResolveAddressTest::MustSucceedWithIPv6First, this));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone();
}
@ -249,50 +251,45 @@ TEST_F(ResolveAddressTest, LocalhostResultHasIPv4FirstWhenIPv6IsntAvalailable) {
address_sorting_override_source_addr_factory_for_testing(mock);
// run the test
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
"localhost:1", "", pollset_set(),
absl::bind_front(&ResolveAddressTest::MustSucceedWithIPv4First, this));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone();
}
TEST_F(ResolveAddressTest, NonNumericDefaultPort) {
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
"localhost", "http", pollset_set(),
absl::bind_front(&ResolveAddressTest::MustSucceed, this));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone();
}
TEST_F(ResolveAddressTest, MissingDefaultPort) {
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
"localhost", "", pollset_set(),
absl::bind_front(&ResolveAddressTest::MustFail, this));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone();
}
TEST_F(ResolveAddressTest, IPv6WithPort) {
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
"[2001:db8::1]:1", "", pollset_set(),
absl::bind_front(&ResolveAddressTest::MustSucceed, this));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone();
}
void TestIPv6WithoutPort(ResolveAddressTest* test, const char* target) {
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
target, "80", test->pollset_set(),
absl::bind_front(&ResolveAddressTest::MustSucceed, test));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
test->PollPollsetUntilRequestDone();
}
@ -311,10 +308,9 @@ TEST_F(ResolveAddressTest, IPv6WithoutPortV4MappedV6) {
void TestInvalidIPAddress(ResolveAddressTest* test, const char* target) {
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
target, "", test->pollset_set(),
absl::bind_front(&ResolveAddressTest::MustFail, test));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
test->PollPollsetUntilRequestDone();
}
@ -329,10 +325,9 @@ TEST_F(ResolveAddressTest, InvalidIPv6Addresses) {
void TestUnparseableHostPort(ResolveAddressTest* test, const char* target) {
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
grpc_core::GetDNSResolver()->ResolveName(
target, "1", test->pollset_set(),
absl::bind_front(&ResolveAddressTest::MustFail, test));
r->Start();
grpc_core::ExecCtx::Get()->Flush();
test->PollPollsetUntilRequestDone();
}
@ -365,11 +360,12 @@ TEST_F(ResolveAddressTest, UnparseableHostPortsBadLocalhostWithPort) {
// test doesn't care what the result is, just that we don't crash etc.
TEST_F(ResolveAddressTest, ImmediateCancel) {
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
auto request_handle = grpc_core::GetDNSResolver()->ResolveName(
"localhost:1", "1", pollset_set(),
absl::bind_front(&ResolveAddressTest::DontCare, this));
r->Start();
r.reset(); // cancel the resolution
if (grpc_core::GetDNSResolver()->Cancel(request_handle)) {
Finish();
}
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone();
}
@ -410,14 +406,14 @@ TEST_F(ResolveAddressTest, CancelWithNonResponsiveDNSServer) {
grpc_ares_test_only_inject_config = InjectNonResponsiveDNSServer;
// Run the test
grpc_core::ExecCtx exec_ctx;
auto r = grpc_core::GetDNSResolver()->ResolveName(
auto request_handle = grpc_core::GetDNSResolver()->ResolveName(
"foo.bar.com:1", "1", pollset_set(),
absl::bind_front(&ResolveAddressTest::MustFailExpectCancelledErrorMessage,
this));
r->Start();
absl::bind_front(&ResolveAddressTest::MustNotBeCalled, this));
grpc_core::ExecCtx::Get()->Flush(); // initiate DNS requests
r.reset(); // cancel the resolution
grpc_core::ExecCtx::Get()->Flush(); // let cancellation work finish
ASSERT_TRUE(grpc_core::GetDNSResolver()->Cancel(request_handle));
Finish();
// let cancellation work finish to ensure the callback is not called
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone();
}

@ -1931,6 +1931,7 @@ src/core/lib/event_engine/channel_args_endpoint_config.h \
src/core/lib/event_engine/default_event_engine_factory.cc \
src/core/lib/event_engine/event_engine.cc \
src/core/lib/event_engine/event_engine_factory.h \
src/core/lib/event_engine/handle_containers.h \
src/core/lib/event_engine/memory_allocator.cc \
src/core/lib/event_engine/resolved_address.cc \
src/core/lib/event_engine/sockaddr.cc \

@ -1723,6 +1723,7 @@ src/core/lib/event_engine/channel_args_endpoint_config.h \
src/core/lib/event_engine/default_event_engine_factory.cc \
src/core/lib/event_engine/event_engine.cc \
src/core/lib/event_engine/event_engine_factory.h \
src/core/lib/event_engine/handle_containers.h \
src/core/lib/event_engine/memory_allocator.cc \
src/core/lib/event_engine/resolved_address.cc \
src/core/lib/event_engine/sockaddr.cc \

Loading…
Cancel
Save