A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 7, 04:00 UTC
[BugFix] avoid infinite loop with VLLM_PORT and get_open_ports_list (#36191)
Signed-off-by: walterbm <walter.beller.morales@gmail.com>
Walter Beller-Morales committed
Mar 6, 2026 at 01:15 UTC
43e77e59abcaf0764aa6851fcc2bc9b86d4afdba
2 files changed
+51
-7
tests/utils_/test_network_utils.py
+20
@@ -7,6 +7,7 @@ import zmq
7
8
from vllm.utils.network_utils import (
9
get_open_port,
10
+ get_open_ports_list,
11
get_tcp_uri,
12
join_host_port,
13
make_zmq_path,
@@ -28,6 +29,25 @@ def test_get_open_port(monkeypatch: pytest.MonkeyPatch):
29
s3.bind(("localhost", get_open_port()))
30
31
32
+def test_get_open_ports_list_with_vllm_port(monkeypatch: pytest.MonkeyPatch):
33
+ with monkeypatch.context() as m:
34
+ m.setenv("VLLM_PORT", "5678")
35
+ ports = get_open_ports_list(5)
36
+ assert len(ports) == 5
37
+ assert len(set(ports)) == 5, "ports must be unique"
38
+
39
+ # verify every port is actually bindable
40
+ sockets = []
41
+ try:
42
+ for p in ports:
43
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
44
+ s.bind(("localhost", p))
45
+ sockets.append(s)
46
+ finally:
47
+ for s in sockets:
48
+ s.close()
49
+
50
+
51
@pytest.mark.parametrize(
52
"path,expected",
53
[
vllm/utils/network_utils.py
+31
-7
@@ -167,16 +167,34 @@ def get_open_port() -> int:
167
168
169
def get_open_ports_list(count: int = 5) -> list[int]:
170
- """Get a list of open ports."""
171
- ports = set[int]()
172
- while len(ports) < count:
173
- ports.add(get_open_port())
174
- return list(ports)
170
+ """Get a list of unique open ports.
171
+
172
+ When VLLM_PORT is set, scans upward from that port, advancing
173
+ the start position after each find so every port is unique.
174
+ """
175
+ ports_set = set[int]()
176
+ if envs.VLLM_PORT is not None:
177
+ next_port = envs.VLLM_PORT
178
+ for _ in range(count):
179
+ port = _get_open_port(start_port=next_port, max_attempts=1000)
180
+ ports_set.add(port)
181
+ next_port = port + 1
182
+ return list(ports_set)
183
+ else:
184
+ while len(ports_set) < count:
185
+ ports_set.add(get_open_port())
186
+
187
+ return list(ports_set)
188
189
177
-def _get_open_port() -> int:
178
- port = envs.VLLM_PORT
190
+def _get_open_port(
191
+ start_port: int | None = None,
192
+ max_attempts: int | None = None,
193
+) -> int:
194
+ start_port = start_port if start_port is not None else envs.VLLM_PORT
195
+ port = start_port
196
if port is not None:
197
+ attempts = 0
198
while True:
199
try:
200
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
@@ -185,6 +203,12 @@ def _get_open_port() -> int:
203
except OSError:
204
port += 1 # Increment port number if already in use
205
logger.info("Port %d is already in use, trying port %d", port - 1, port)
206
+ attempts += 1
207
+ if max_attempts is not None and attempts >= max_attempts:
208
+ raise RuntimeError(
209
+ f"Could not find open port after {max_attempts} "
210
+ f"attempts starting from port {start_port}"
211
+ )
212
# try ipv4
213
try:
214
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: