Skip to content

Commit e1f00ae

Browse files
Yicheng-Lu-llllpeterxcli
authored andcommitted
[Core] Consolidate find_free_port to network_utils (ray-project#58304)
This PR is a follow-up to ray-project#56147 (comment) The `find_free_port()` function was duplicated across multiple locations in the codebase. This PR consolidates all implementations into a single canonical location. --------- Signed-off-by: Yicheng-Lu-llll <luyc58576@gmail.com> Signed-off-by: peterxcli <peterxcli@gmail.com>
1 parent 64e242b commit e1f00ae

File tree

17 files changed

+31
-53
lines changed

17 files changed

+31
-53
lines changed

doc/source/ray-core/examples/lm/ray_train.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ def find_free_port(self):
8080
"""Finds a free port on the current node."""
8181
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
8282
s.bind(("", 0))
83-
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
8483
return s.getsockname()[1]
8584

8685

python/ray/_common/network_utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import socket
2+
from contextlib import closing
23
from functools import lru_cache
34
from typing import Optional, Tuple, Union
45

@@ -93,3 +94,18 @@ def is_localhost(host: str) -> bool:
9394
True if the host is a localhost address, False otherwise.
9495
"""
9596
return host in ("localhost", "127.0.0.1", "::1")
97+
98+
99+
def find_free_port(family: socket.AddressFamily = socket.AF_INET) -> int:
100+
"""Find a free port on the local machine.
101+
102+
Args:
103+
family: The socket address family (AF_INET for IPv4, AF_INET6 for IPv6).
104+
Defaults to AF_INET.
105+
106+
Returns:
107+
An available port number.
108+
"""
109+
with closing(socket.socket(family, socket.SOCK_STREAM)) as s:
110+
s.bind(("", 0))
111+
return s.getsockname()[1]

python/ray/_private/test_utils.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,14 +1850,6 @@ def job_hook(**kwargs):
18501850
sys.exit(0)
18511851

18521852

1853-
def find_free_port() -> int:
1854-
sock = socket.socket()
1855-
sock.bind(("", 0))
1856-
port = sock.getsockname()[1]
1857-
sock.close()
1858-
return port
1859-
1860-
18611853
def wandb_setup_api_key_hook():
18621854
"""
18631855
Example external hook to set up W&B API key in

python/ray/air/_internal/util.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
import logging
33
import os
44
import queue
5-
import socket
65
import threading
7-
from contextlib import closing
86
from typing import Optional
97

108
import numpy as np
@@ -14,13 +12,6 @@
1412
logger = logging.getLogger(__name__)
1513

1614

17-
def find_free_port(family=socket.AF_INET):
18-
with closing(socket.socket(family, socket.SOCK_STREAM)) as s:
19-
s.bind(("", 0))
20-
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
21-
return s.getsockname()[1]
22-
23-
2415
def is_nan(value):
2516
return np.isnan(value)
2617

python/ray/dashboard/modules/aggregator/tests/test_aggregator_agent.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
from google.protobuf.timestamp_pb2 import Timestamp
99

1010
import ray.dashboard.consts as dashboard_consts
11+
from ray._common.network_utils import find_free_port
1112
from ray._private import ray_constants
12-
from ray._private.test_utils import (
13-
find_free_port,
14-
wait_for_condition,
15-
)
13+
from ray._private.test_utils import wait_for_condition
1614
from ray._private.utils import init_grpc_channel
1715
from ray._raylet import GcsClient
1816
from ray.core.generated.common_pb2 import (

python/ray/dashboard/modules/reporter/tests/test_healthz.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
import requests
55

66
import ray._private.ray_constants as ray_constants
7+
from ray._common.network_utils import find_free_port
78
from ray._common.test_utils import wait_for_condition
8-
from ray._private.test_utils import find_free_port
99
from ray.tests.conftest import * # noqa: F401 F403
1010

1111

python/ray/data/tests/mock_server.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ def _is_port_available(host, port):
2121
"""Check if a port is available for use."""
2222
try:
2323
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
24-
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
2524
s.bind((host, port))
2625
return True
2726
except OSError:
@@ -44,7 +43,6 @@ def _find_available_port(host, preferred_port, max_attempts=10):
4443
# If all else fails, let the OS pick a port
4544
try:
4645
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
47-
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
4846
s.bind((host, 0)) # Let OS pick port
4947
_, port = s.getsockname()
5048
return port

python/ray/experimental/collective/util.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import socket
2-
from contextlib import closing
32
from typing import TYPE_CHECKING, Tuple
43

54
import ray
6-
from ray._common.network_utils import is_ipv6
5+
from ray._common.network_utils import find_free_port, is_ipv6
76
from ray.experimental.collective.collective_tensor_transport import (
87
CollectiveTensorTransport,
98
)
@@ -65,13 +64,5 @@ def device_match_transport(device: "torch.device", tensor_transport: Backend) ->
6564
def get_address_and_port() -> Tuple[str, int]:
6665
"""Returns the IP address and a free port on this node."""
6766
addr = ray.util.get_node_ip_address()
68-
with closing(
69-
socket.socket(
70-
socket.AF_INET6 if is_ipv6(addr) else socket.AF_INET, socket.SOCK_STREAM
71-
)
72-
) as s:
73-
s.bind(("", 0))
74-
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
75-
port = s.getsockname()[1]
76-
67+
port = find_free_port(socket.AF_INET6 if is_ipv6(addr) else socket.AF_INET)
7768
return addr, port

python/ray/tests/conftest.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,13 @@
2222

2323
import ray
2424
import ray._private.ray_constants as ray_constants
25-
from ray._common.network_utils import build_address
25+
from ray._common.network_utils import build_address, find_free_port
2626
from ray._common.test_utils import wait_for_condition
2727
from ray._private.conftest_utils import set_override_dashboard_url # noqa: F401
2828
from ray._private.runtime_env import virtualenv_utils
2929
from ray._private.test_utils import (
3030
RayletKiller,
3131
external_redis_test_enabled,
32-
find_free_port,
3332
get_and_run_resource_killer,
3433
get_redis_cli,
3534
init_error_pubsub,

python/ray/tests/test_gcs_utils.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111
import ray
1212
import ray._private.gcs_utils as gcs_utils
1313
import ray._private.ray_constants as ray_constants
14-
from ray._common.network_utils import parse_address
14+
from ray._common.network_utils import find_free_port, parse_address
1515
from ray._common.test_utils import async_wait_for_condition
1616
from ray._private.test_utils import (
1717
external_redis_test_enabled,
18-
find_free_port,
1918
generate_system_config_map,
2019
)
2120
from ray._raylet import GcsClient, NodeID

0 commit comments

Comments
 (0)