This is an automated email from the ASF dual-hosted git repository. alexey pushed a commit to branch branch-1.18.x in repository https://gitbox.apache.org/repos/asf/kudu.git
The following commit(s) were added to refs/heads/branch-1.18.x by this push: new 1b825e6a6 [socket] Fix test failure caused due to unsupported socket option 1b825e6a6 is described below commit 1b825e6a6bf3a0939885173b1b143ac51ed778c7 Author: Ashwani Raina <ara...@cloudera.com> AuthorDate: Mon May 12 21:27:15 2025 +0530 [socket] Fix test failure caused due to unsupported socket option setsockopt() system call doesn't support SO_REUSEPORT for a Unix domain socket. Due to this, following tests fail on certain linux versions (e.g. v6.15): - client-test.TestConnectViaUnixSocket - dns_alias-itest.TestBasic Although there is no support available, a graceful error handling was recently added as part of [1] commit. Linux kernel versions where [1] is present, error out with appropriate message and test also fails expectedly. However, for linux kernel versions (e.g. v5.15) where [1] is not present, the tests may pass, but setting of SO_REUSEPORT socket option may have no effect at all, potentially leading to confusion and undefined behavior in tests. The patch does the following to fix this: 1. Error out with appropriate error message if setting socket option (i.e. SO_REUSEPORT) on a Unix domain socket. 2. Add a group flag validator to ensure either of two flags is set: --rpc_listen_on_unix_domain_socket or --rpc_reuseport. 3. Explicitly initialise --rpc_reuseport flag in tests wherever required as per test expectations. [1] https://github.com/torvalds/linux/commit/5b0af621c3f6ef9261cf6067812f2fd9943acb4b Change-Id: Ice00b1c4fd1df78fa84c3dd2a79c968a4a91cc21 Reviewed-on: http://gerrit.cloudera.org:8080/22882 Reviewed-by: Alexey Serbin <ale...@apache.org> Tested-by: Alexey Serbin <ale...@apache.org> (cherry picked from commit 01e0aa93211c968d2dead9cf85bf54d8f9fec18c) Reviewed-on: http://gerrit.cloudera.org:8080/22961 Reviewed-by: Abhishek Chennaka <achenn...@cloudera.com> Tested-by: Kudu Jenkins --- src/kudu/integration-tests/dns_alias-itest.cc | 6 +++--- src/kudu/master/mini_master.cc | 6 +++++- src/kudu/rpc/messenger.cc | 5 +++++ src/kudu/server/server_base.cc | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/kudu/integration-tests/dns_alias-itest.cc b/src/kudu/integration-tests/dns_alias-itest.cc index 58735bded..810400230 100644 --- a/src/kudu/integration-tests/dns_alias-itest.cc +++ b/src/kudu/integration-tests/dns_alias-itest.cc @@ -19,6 +19,7 @@ #include <functional> #include <memory> #include <string> +#include <type_traits> #include <utility> #include <vector> @@ -37,7 +38,6 @@ #include "kudu/mini-cluster/mini_cluster.h" #include "kudu/rpc/rpc_controller.h" #include "kudu/tserver/tserver.pb.h" -#include "kudu/tserver/tserver_service.proxy.h" #include "kudu/util/metrics.h" #include "kudu/util/monotime.h" #include "kudu/util/net/net_util.h" @@ -218,8 +218,8 @@ class DnsAliasWithUnixSocketsITest : public DnsAliasITest { // it's local to a tserver. FLAGS_host_for_tests = Substitute("$0.$1", kTServerHostPrefix, kTServerIdxWithLocalClient); FLAGS_client_use_unix_domain_sockets = true; - SetUpCluster({ "--rpc_listen_on_unix_domain_socket=true" }, - { "--rpc_listen_on_unix_domain_socket=true" }); + SetUpCluster({ "--rpc_listen_on_unix_domain_socket=true", "--rpc_reuseport=false" }, + { "--rpc_listen_on_unix_domain_socket=true", "--rpc_reuseport=false" }); } protected: const int kTServerIdxWithLocalClient = 0; diff --git a/src/kudu/master/mini_master.cc b/src/kudu/master/mini_master.cc index e8bb0571f..480c7073e 100644 --- a/src/kudu/master/mini_master.cc +++ b/src/kudu/master/mini_master.cc @@ -45,6 +45,7 @@ using std::vector; using strings::Substitute; DECLARE_bool(enable_minidumps); +DECLARE_bool(rpc_listen_on_unix_domain_socket); DECLARE_bool(rpc_server_allow_ephemeral_ports); namespace kudu { @@ -57,7 +58,10 @@ MiniMaster::MiniMaster(string fs_root, HostPort rpc_bind_addr, int num_data_dirs FLAGS_enable_minidumps = false; HostPort web_bind_addr(rpc_bind_addr_.host(), /*port=*/ 0); opts_.rpc_opts.rpc_bind_addresses = rpc_bind_addr_.ToString(); - opts_.rpc_opts.rpc_reuseport = true; + // A MiniMaster enables SO_REUSEPORT on its RPC socket to simplify operation + // of multi-master mini-clusters, but the SO_REUSEPORT option isn't applicable + // for Unix domain sockets. + opts_.rpc_opts.rpc_reuseport = !FLAGS_rpc_listen_on_unix_domain_socket; opts_.webserver_opts.bind_interface = web_bind_addr.host(); opts_.webserver_opts.port = web_bind_addr.port(); opts_.set_block_cache_metrics_policy(Cache::ExistingMetricsPolicy::kKeep); diff --git a/src/kudu/rpc/messenger.cc b/src/kudu/rpc/messenger.cc index 15db7d09c..248f9055c 100644 --- a/src/kudu/rpc/messenger.cc +++ b/src/kudu/rpc/messenger.cc @@ -259,6 +259,11 @@ Status Messenger::AddAcceptorPool(const Sockaddr& accept_addr, RETURN_NOT_OK(sock.Init(accept_addr.family(), 0)); RETURN_NOT_OK(sock.SetReuseAddr(true)); if (reuseport_) { + // SO_REUSEPORT socket option is not applicable to Unix domain sockets. + if (PREDICT_FALSE(accept_addr.is_unix())) { + return Status::ConfigurationError( + "Port reuse is not applicable to Unix domain sockets."); + } RETURN_NOT_OK(sock.SetReusePort(true)); } RETURN_NOT_OK(sock.Bind(accept_addr)); diff --git a/src/kudu/server/server_base.cc b/src/kudu/server/server_base.cc index 6ba567a29..6638375f8 100644 --- a/src/kudu/server/server_base.cc +++ b/src/kudu/server/server_base.cc @@ -319,6 +319,7 @@ DEFINE_uint64(tcmalloc_max_total_thread_cache_bytes, 128 * 1024 * 1024, TAG_FLAG(tcmalloc_max_total_thread_cache_bytes, advanced); TAG_FLAG(tcmalloc_max_total_thread_cache_bytes, experimental); +DECLARE_bool(rpc_reuseport); DECLARE_bool(use_hybrid_clock); DECLARE_int32(dns_resolver_max_threads_num); DECLARE_uint32(dns_resolver_cache_capacity_mb); @@ -512,6 +513,19 @@ bool ValidateEitherJWKSFilePathOrUrlSet() { GROUP_FLAG_VALIDATOR(jwks_file_or_url_set_validator, &ValidateEitherJWKSFilePathOrUrlSet); +bool ValidateSocketOptionCompatibility() { + if (FLAGS_rpc_listen_on_unix_domain_socket && FLAGS_rpc_reuseport) { + LOG(ERROR) << Substitute( + "Either --rpc_listen_on_unix_domain_socket or --rpc_reuseport should " + "be set, reuse of port is not applicable to Unix domain sockets."); + return false; + } + + return true; +} + +GROUP_FLAG_VALIDATOR(socket_options_compatibility, ValidateSocketOptionCompatibility); + } // namespace static bool ValidateRpcAuthentication(const char* flag_name, const string& flag_value) {