Skip to content

Commit c9c4203

Browse files
authored
check open ports for which address families we can bind to (#5621)
1 parent b052299 commit c9c4203

File tree

1 file changed

+46
-7
lines changed

1 file changed

+46
-7
lines changed

reflex/utils/processes.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,41 @@ def _can_bind_at_port(
7878
return True
7979

8080

81-
def is_process_on_port(port: int) -> bool:
81+
def _can_bind_at_any_port(address_family: socket.AddressFamily | int) -> bool:
82+
"""Check if any port is available for binding.
83+
84+
Args:
85+
address_family: The address family (e.g., socket.AF_INET or socket.AF_INET6).
86+
87+
Returns:
88+
Whether any port is available for binding.
89+
"""
90+
with closing(socket.socket(address_family, socket.SOCK_STREAM)) as sock:
91+
try:
92+
sock.bind(("", 0)) # Bind to any available port
93+
except (OverflowError, PermissionError, OSError) as e:
94+
console.debug(f"Unable to bind to any port for {address_family}: {e}")
95+
return False
96+
return True
97+
98+
99+
def is_process_on_port(
100+
port: int,
101+
address_families: Sequence[socket.AddressFamily | int] = (
102+
socket.AF_INET,
103+
socket.AF_INET6,
104+
),
105+
) -> bool:
82106
"""Check if a process is running on the given port.
83107
84108
Args:
85109
port: The port.
110+
address_families: The address families to check (default: IPv4 and IPv6).
86111
87112
Returns:
88113
Whether a process is running on the given port.
89114
"""
90-
return (
91-
not _can_bind_at_port(socket.AF_INET, "", port) # Test IPv4 local network
92-
or not _can_bind_at_port(socket.AF_INET6, "", port) # Test IPv6 local network
93-
)
115+
return any(not _can_bind_at_port(family, "", port) for family in address_families)
94116

95117

96118
MAXIMUM_PORT = 2**16 - 1
@@ -113,13 +135,30 @@ def handle_port(service_name: str, port: int, auto_increment: bool) -> int:
113135
"""
114136
console.debug(f"Checking if {service_name.capitalize()} port: {port} is in use.")
115137

116-
if not is_process_on_port(port):
138+
families = [
139+
address_family
140+
for address_family in (socket.AF_INET, socket.AF_INET6)
141+
if _can_bind_at_any_port(address_family)
142+
]
143+
144+
if not families:
145+
console.error(
146+
f"Unable to bind to any port for {service_name}. "
147+
"Please check your network configuration."
148+
)
149+
raise click.exceptions.Exit(1)
150+
151+
console.debug(
152+
f"Checking if {service_name.capitalize()} port: {port} is in use for families: {families}."
153+
)
154+
155+
if not is_process_on_port(port, families):
117156
console.debug(f"{service_name.capitalize()} port: {port} is not in use.")
118157
return port
119158

120159
if auto_increment:
121160
for new_port in range(port + 1, MAXIMUM_PORT + 1):
122-
if not is_process_on_port(new_port):
161+
if not is_process_on_port(new_port, families):
123162
console.info(
124163
f"The {service_name} will run on port [bold underline]{new_port}[/bold underline]."
125164
)

0 commit comments

Comments
 (0)