From 89f87ab343500cd3934def488ef7dd5c42abbb25 Mon Sep 17 00:00:00 2001 From: Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Date: Sun, 6 Jul 2025 17:33:52 -0400 Subject: [PATCH 1/7] [py] Allow free_port() to bind to IPv6 if IPv4 is unavailable --- py/selenium/webdriver/common/utils.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/py/selenium/webdriver/common/utils.py b/py/selenium/webdriver/common/utils.py index f022b617ec59f..d8fb55015efda 100644 --- a/py/selenium/webdriver/common/utils.py +++ b/py/selenium/webdriver/common/utils.py @@ -27,9 +27,17 @@ def free_port() -> int: - """Determines a free port using sockets.""" - free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - free_socket.bind(("127.0.0.1", 0)) + """Determines a free port using sockets. + + First try IPv4, but use IPv6 if it doesn't exist (IPv6-only system). + """ + try: + # IPv4 + free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + free_socket.bind(("127.0.0.1", 0)) + except OSError: + free_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + free_socket.bind(("::1", 0)) free_socket.listen(5) port: int = free_socket.getsockname()[1] free_socket.close() From ee82768230fea2bcadc9b687ccacf94a333bf3a9 Mon Sep 17 00:00:00 2001 From: Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Date: Sun, 6 Jul 2025 18:12:40 -0400 Subject: [PATCH 2/7] [py] Fix comment --- py/selenium/webdriver/common/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/py/selenium/webdriver/common/utils.py b/py/selenium/webdriver/common/utils.py index d8fb55015efda..db401ca0fd94f 100644 --- a/py/selenium/webdriver/common/utils.py +++ b/py/selenium/webdriver/common/utils.py @@ -29,13 +29,14 @@ def free_port() -> int: """Determines a free port using sockets. - First try IPv4, but use IPv6 if it doesn't exist (IPv6-only system). + First try IPv4, but use IPv6 if it can't bind (IPv6-only system). """ try: # IPv4 free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) free_socket.bind(("127.0.0.1", 0)) except OSError: + # IPv6 free_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) free_socket.bind(("::1", 0)) free_socket.listen(5) From e1b37167d8262e6bfdf7dd3faaddb0312b5cbbdf Mon Sep 17 00:00:00 2001 From: Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Date: Mon, 7 Jul 2025 10:09:14 -0400 Subject: [PATCH 3/7] [py] Prevent socket resource leak --- py/selenium/webdriver/common/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/py/selenium/webdriver/common/utils.py b/py/selenium/webdriver/common/utils.py index db401ca0fd94f..15499d3dda562 100644 --- a/py/selenium/webdriver/common/utils.py +++ b/py/selenium/webdriver/common/utils.py @@ -31,11 +31,14 @@ def free_port() -> int: First try IPv4, but use IPv6 if it can't bind (IPv6-only system). """ + free_socket = None try: # IPv4 free_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) free_socket.bind(("127.0.0.1", 0)) except OSError: + if free_socket: + free_socket.close() # IPv6 free_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) free_socket.bind(("::1", 0)) From 814af8421ff1d1663fdc6a4e5efbcf6c32ac33cd Mon Sep 17 00:00:00 2001 From: Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Date: Mon, 7 Jul 2025 10:15:35 -0400 Subject: [PATCH 4/7] [py] Better error handling --- py/selenium/webdriver/common/utils.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/py/selenium/webdriver/common/utils.py b/py/selenium/webdriver/common/utils.py index 15499d3dda562..64bd50ad64786 100644 --- a/py/selenium/webdriver/common/utils.py +++ b/py/selenium/webdriver/common/utils.py @@ -40,8 +40,11 @@ def free_port() -> int: if free_socket: free_socket.close() # IPv6 - free_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - free_socket.bind(("::1", 0)) + try: + free_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + free_socket.bind(("::1", 0)) + except OSError: + raise RuntimeError("Can't find free port (Unable to bind to IPv4 or IPv6)") free_socket.listen(5) port: int = free_socket.getsockname()[1] free_socket.close() From 0eca4f5e0acc40d9eabfcaebc0981f95481f77b0 Mon Sep 17 00:00:00 2001 From: Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Date: Mon, 7 Jul 2025 10:21:06 -0400 Subject: [PATCH 5/7] [py] Better error handling --- py/selenium/webdriver/common/utils.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/py/selenium/webdriver/common/utils.py b/py/selenium/webdriver/common/utils.py index 64bd50ad64786..7613af0ae2158 100644 --- a/py/selenium/webdriver/common/utils.py +++ b/py/selenium/webdriver/common/utils.py @@ -45,9 +45,13 @@ def free_port() -> int: free_socket.bind(("::1", 0)) except OSError: raise RuntimeError("Can't find free port (Unable to bind to IPv4 or IPv6)") - free_socket.listen(5) - port: int = free_socket.getsockname()[1] - free_socket.close() + try: + free_socket.listen(5) + port: int = free_socket.getsockname()[1] + except Exception as e: + raise RuntimeError(f"Can't find free port ({e})") + finally: + free_socket.close() return port From 7e9888ae784733af304d600d900bcec5c2e9efc9 Mon Sep 17 00:00:00 2001 From: Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Date: Mon, 7 Jul 2025 10:26:54 -0400 Subject: [PATCH 6/7] [py] Add character --- py/selenium/webdriver/common/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/selenium/webdriver/common/utils.py b/py/selenium/webdriver/common/utils.py index 7613af0ae2158..63e2fc545e7ae 100644 --- a/py/selenium/webdriver/common/utils.py +++ b/py/selenium/webdriver/common/utils.py @@ -49,7 +49,7 @@ def free_port() -> int: free_socket.listen(5) port: int = free_socket.getsockname()[1] except Exception as e: - raise RuntimeError(f"Can't find free port ({e})") + raise RuntimeError(f"Can't find free port: ({e})") finally: free_socket.close() return port From 004d2732ebc35ee6390a1d471043bb7a1ffad5a9 Mon Sep 17 00:00:00 2001 From: Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Date: Thu, 10 Jul 2025 14:27:22 -0400 Subject: [PATCH 7/7] [py] Remove call to socket.listen() --- py/selenium/webdriver/common/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/py/selenium/webdriver/common/utils.py b/py/selenium/webdriver/common/utils.py index 63e2fc545e7ae..4bc16a9400e8e 100644 --- a/py/selenium/webdriver/common/utils.py +++ b/py/selenium/webdriver/common/utils.py @@ -46,7 +46,6 @@ def free_port() -> int: except OSError: raise RuntimeError("Can't find free port (Unable to bind to IPv4 or IPv6)") try: - free_socket.listen(5) port: int = free_socket.getsockname()[1] except Exception as e: raise RuntimeError(f"Can't find free port: ({e})")