Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Check if port is available to listen on #36428

Open
przemek-kieszkowski opened this issue Apr 23, 2024 · 5 comments
Open

Feature Request: Check if port is available to listen on #36428

przemek-kieszkowski opened this issue Apr 23, 2024 · 5 comments

Comments

@przemek-kieszkowski
Copy link

What version of gRPC and what language are you using?

1.62.1

What operating system (Linux, Windows,...) and version?

Linux

What runtime / compiler are you using (e.g. python version or version of gcc)

gcc 11.4.0

What did you do?

This is example code:

void StartServer() {
  grpc::ServerBuilder builder;
  std::string server_address("0.0.0.0:0");  // Use port 0 for automatic port selection
  int port_selected = 1;

  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials(), &port_selected);
  if (port_selected == 0) {
    std::cerr << "Failed to bind to any port. Please check the server configuration or system permissions."
              << std::endl;
    return;  // Exit if no port is available
  }
  std::cout << "Server listening on port: " << port_selected << std::endl;

  std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
  std::cout << "Server listening on port: " << port_selected << std::endl;

  server->Wait();
}

It seems that port_selected variable is set to correct value after call builder.BuildAndStart()

Server listening on port: 1
I0423 13:30:17.945743606 1354375 server_builder.cc:352]                Synchronous server. Num CQs: 1, Min pollers: 1, Max Pollers: 2, CQ timeout (msec): 10000
D0423 13:30:17.945906896 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "priority_experimental"
D0423 13:30:17.945927849 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "outlier_detection_experimental"
D0423 13:30:17.945942096 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "weighted_target_experimental"
D0423 13:30:17.945949639 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "pick_first"
D0423 13:30:17.945965493 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "round_robin"
D0423 13:30:17.945974014 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "weighted_round_robin"
D0423 13:30:17.946027513 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "grpclb"
D0423 13:30:17.946048396 1354375 dns_resolver_plugin.cc:52]            Using ares dns resolver
D0423 13:30:17.946077939 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "rls_experimental"
D0423 13:30:17.946140727 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "xds_cluster_manager_experimental"
D0423 13:30:17.946158536 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "xds_cluster_impl_experimental"
D0423 13:30:17.946167057 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "cds_experimental"
D0423 13:30:17.946175578 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "xds_override_host_experimental"
D0423 13:30:17.946192829 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "xds_wrr_locality_experimental"
D0423 13:30:17.946201838 1354375 lb_policy_registry.cc:46]             registering LB policy factory for "ring_hash_experimental"
D0423 13:30:17.946210918 1354375 certificate_provider_registry.cc:33]  registering certificate provider factory for "file_watcher"
D0423 13:30:17.946276779 1354375 channel_init.cc:157]                  Filter server-auth not registered, but is referenced in the after clause of grpc-server-authz when building channel stack SERVER_CHANNEL
I0423 13:30:17.947438878 1354375 ev_epoll1_linux.cc:359]               grpc epoll fd: 32
I20240423 13:30:17.947562 1354409 ArrayParam.cpp:122] CArrayParam::SetPendingParam set_data false set_string false)
I0423 13:30:17.947662861 1354375 tcp_socket_utils.cc:629]              TCP_USER_TIMEOUT is available. TCP_USER_TIMEOUT will be used thereafter
Server listening on port: 34995

What did you expect to see?

Correct port value after call builder.AddListeningPort

What did you see instead?

Make sure you include information that can help us debug (full error message, exception listing, stack trace, logs).

See TROUBLESHOOTING.md for how to diagnose problems better.

Anything else we should know about your project / environment?

@przemek-kieszkowski
Copy link
Author

detailed Linux version:
Linux admin1-Vostro-5415 6.5.0-27-generic #28~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Mar 15 10:51:06 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

@przemek-kieszkowski
Copy link
Author

I think this seems to be expected behavior.
Please tell me how to handle belowe scenario:

  1. I have configuration where I prefer to use specified port number
  2. If setup connection fails on this port I would like to ask grpc server to chose any number and then tell me this number
  3. I prefer to use: builder.AddChannelArgument(GRPC_ARG_ALLOW_REUSEPORT, 0);

@yashykt
Copy link
Member

yashykt commented May 14, 2024

You are right. That is indeed the expected outcome.

Unfortunately, we do not have an API that allows checking whether a port is available or not.

@yashykt
Copy link
Member

yashykt commented May 14, 2024

A possible workaround is to write custom code, maybe by checking the contents of /proc/net/tcp to see if the port is available or not.

I'm going to keep this around to see if others are interested in this. I'm unsure if this is something gRPC should be doing.

@yashykt yashykt changed the title It seems that port_selected variable from AddListeningPort is set to correct value after call builder.BuildAndStart() Feature Request: Check if port is available to listen on May 14, 2024
@przemek-kieszkowski
Copy link
Author

Thanks, My proposal to API extension:
ServerBuilder& AddListeningPort(
const std::string& addr_uri,
std::shared_ptrgrpc::ServerCredentials creds,
int* selected_port = nullptr);

case1:
selected_port == nullptr
Server is try to bind to port given in addr_uri parameter. If it is already occupied - it fails BuildAndStart

case2:
selected_port == pointer to int
(a) if PortNumber in addr_uri is different than 0:

  • server try to bind port passed in addr_uri - on success returns this value in selected_port

if fails in(a) (or PortNumber in addr_uri == 0)

  • server try to bind any port number and returns this value in selected_port

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants