bneradt commented on code in PR #12291:
URL: https://github.com/apache/trafficserver/pull/12291#discussion_r2153091760
##########
tests/gold_tests/autest-site/ports.py:
##########
@@ -30,6 +31,72 @@
g_ports = None # ports we can use
+class AsyncPortQueue(OrderedSetQueue):
+
+ def __init__(self):
+ super().__init__()
+ self._listening_ports = _get_listening_ports()
+
+ async def select_available(self, amount, dmin, dmax):
+ rmin = dmin - 2000
+ rmax = 65536 - dmax
+
+ port_tasks = []
+ await asyncio.gather(*port_tasks)
+ if rmax > amount:
+ # Fill in ports, starting above the upper OS-usable port range.
+ port = dmax + 1
+ while port < 65536 and self.qsize() < amount:
+ port_tasks.append(self._check_port(port))
+ port += 1
+ if rmin > amount and self.qsize() < amount:
+ port = 2001
+ # Fill in more ports, starting at 2001, well above well known
ports,
+ # and going up until the minimum port range used by the OS.
+ while port < dmin and self.qsize() < amount:
+ port_tasks.append(self._check_port(port))
+ port += 1
+
+ await asyncio.gather(*port_tasks)
+
+ async def _check_port(self, port):
+ if await self._is_port_open(port):
+ host.WriteDebug('_setup_port_queue', f"Rejecting an already open
port: {port}")
+ else:
+ host.WriteDebug('_setup_port_queue', f"Adding a possible port to
connect to: {port}")
+ self.put(port)
+
+ async def _is_port_open(self, port, address=None):
+ ret = False
+ if address is None:
+ address = "localhost"
+
+ if port in self._listening_ports:
+ host.WriteDebug('PortOpen', f"{port} is open because it is in the
listening sockets set.")
+ return True
+
+ try:
+ # Try to connect on that port. If we can connect on it, then
someone is
+ # listening on that port and therefore the port is open.
+ reader, writer = await asyncio.open_connection(address, port,
limit=1)
+ writer.close()
+ await writer.wait_closed()
+ ret = True
+ host.WriteDebug(
+ 'PortOpen', f"Connection to port {port} succeeded, the port is
open, "
+ "and a future connection cannot use it")
+ except ConnectionRefusedError:
Review Comment:
Running this locally, in a Rancher docker vm on my Apple silicon macbook
pro, I get the following exception:
```
╰─➤ ./autest.sh --sandbox /tmp/sb --clean=none -f emergency
20:07:30 [4/186]
Running Test emergency:E
Generating Report: --------------
Test: emergency: Exception
File: emergency.test.py
Directory:
/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/shutdown
Reason: Traceback (most recent call last):
File
"/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/autest-site/ports.py",
line 246, in _setup_port_queue
loop = asyncio.get_running_loop()
RuntimeError: no running event loop
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File
"/home/bneradt/.local/share/virtualenvs/tests-68jNU4xi/lib/python3.13/site-packages/autest/core/runtesttask.py",
line 34, in __call__
tl = self.__logic.Run(self.__test)
File
"/home/bneradt/.local/share/virtualenvs/tests-68jNU4xi/lib/python3.13/site-packages/autest/runlogic/runlogic.py",
line 18, in Run
if not tmp.Start(obj):
~~~~~~~~~^^^^^
File
"/home/bneradt/.local/share/virtualenvs/tests-68jNU4xi/lib/python3.13/site-packages/autest/runlogic/test.py",
line 90, in Start
loadTest(self.__test)
~~~~~~~~^^^^^^^^^^^^^
File
"/home/bneradt/.local/share/virtualenvs/tests-68jNU4xi/lib/python3.13/site-packages/autest/core/test.py",
line 292, in loadTest
execFile(fileName, locals, locals)
~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/home/bneradt/.local/share/virtualenvs/tests-68jNU4xi/lib/python3.13/site-packages/autest/common/execfile.py",
line 16, in execFile
exec(safeCompile(f.read(), fname), globals, locals)
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/shutdown/emergency.test.py",
line 25, in <module>
ts = Test.MakeATSProcess('ts')
File
"/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/autest-site/trafficserver.test.ext",
line 348, in MakeATSProcess
get_port(p, "port")
~~~~~~~~^^^^^^^^^^^
File
"/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/autest-site/ports.py",
line 282, in get_port
_setup_port_queue()
~~~~~~~~~~~~~~~~~^^
File
"/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/autest-site/ports.py",
line 249, in _setup_port_queue
asyncio.run(async_setup())
~~~~~~~~~~~^^^^^^^^^^^^^^^
File "/usr/lib64/python3.13/asyncio/runners.py", line 195, in run
return runner.run(main)
~~~~~~~~~~^^^^^^
File "/usr/lib64/python3.13/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/usr/lib64/python3.13/asyncio/base_events.py", line 719, in
run_until_complete
return future.result()
~~~~~~~~~~~~~^^
File
"/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/autest-site/ports.py",
line 243, in async_setup
await g_ports.select_available(amount, dmin, dmax)
File
"/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/autest-site/ports.py",
line 60, in select_available
await asyncio.gather(*port_tasks)
File
"/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/autest-site/ports.py",
line 63, in _check_port
if await self._is_port_open(port):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/home/bneradt/src/ts_asf_master_pr_reviews/tests/gold_tests/autest-site/ports.py",
line 81, in _is_port_open
reader, writer = await asyncio.open_connection(address, port,
limit=1)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.13/asyncio/streams.py", line 48, in
open_connection
transport, _ = await loop.create_connection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lambda: protocol, host, port, **kwds)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.13/asyncio/base_events.py", line 1168, in
create_connection
raise OSError('Multiple exceptions: {}'.format(
', '.join(str(exc) for exc in exceptions)))
OSError: Multiple exceptions: [Errno 111] Connect call failed ('::1',
61001, 0, 0), [Errno 111] Connect call failed ('127.0.0.1', 61001)
Total of 1 test
Unknown: 0
Exception: 1
Failed: 0
Warning: 0
Skipped: 0
Passed: 0
```
It seems like we need to add OSError to the list of handles exceptions:
```patch
diff --git a/tests/gold_tests/autest-site/ports.py
b/tests/gold_tests/autest-site/ports.py
index 0b8ec00e5..c5259634c 100644
--- a/tests/gold_tests/autest-site/ports.py
+++ b/tests/gold_tests/autest-site/ports.py
@@ -85,7 +85,7 @@ class AsyncPortQueue(OrderedSetQueue):
host.WriteDebug(
'PortOpen', f"Connection to port {port} succeeded, the port
is open, "
"and a future connection cannot use it")
- except ConnectionRefusedError:
+ except (ConnectionRefusedError, OSError):
host.WriteDebug(
'PortOpen', f"socket error for port {port}, port is closed,
"
"and therefore a future connection can use it")
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]