Skip to content

Commit 4bbb3f6

Browse files
authored
Merge pull request #2365 from asimurka/fix/async-task-pending
LCORE-1627: fix e2e proxy teardown asyncio task warnings
2 parents 0ae71d1 + 8bbb09b commit 4bbb3f6

3 files changed

Lines changed: 36 additions & 6 deletions

File tree

tests/e2e/features/steps/proxy.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,11 @@ def _stop_proxy(context: Context, attr: str, loop_attr: str) -> None:
286286
except Exception:
287287
pass
288288
loop.call_soon_threadsafe(loop.stop)
289-
time.sleep(0.5)
289+
thread = getattr(proxy, "_thread", None)
290+
if thread is not None:
291+
thread.join(timeout=30)
292+
else:
293+
time.sleep(0.5)
290294
if hasattr(context, attr):
291295
delattr(context, attr)
292296
if hasattr(context, loop_attr):
@@ -368,10 +372,21 @@ def start_tunnel_proxy(context: Context, port: int) -> None:
368372

369373
def run_proxy() -> None:
370374
asyncio.set_event_loop(loop)
371-
loop.run_until_complete(proxy.start())
372-
loop.run_forever()
375+
try:
376+
loop.run_until_complete(proxy.start())
377+
loop.run_forever()
378+
finally:
379+
# Cancel leftover handler tasks so the loop can close cleanly.
380+
if pending := asyncio.all_tasks(loop):
381+
for task in pending:
382+
task.cancel()
383+
loop.run_until_complete(
384+
asyncio.gather(*pending, return_exceptions=True)
385+
)
386+
loop.close()
373387

374388
thread = threading.Thread(target=run_proxy, daemon=True)
389+
proxy._thread = thread
375390
thread.start()
376391
time.sleep(1)
377392

@@ -463,10 +478,21 @@ def start_interception_proxy(context: Context, port: int) -> None:
463478

464479
def run_proxy() -> None:
465480
asyncio.set_event_loop(loop)
466-
loop.run_until_complete(proxy.start())
467-
loop.run_forever()
481+
try:
482+
loop.run_until_complete(proxy.start())
483+
loop.run_forever()
484+
finally:
485+
# Cancel leftover handler tasks so the loop can close cleanly.
486+
if pending := asyncio.all_tasks(loop):
487+
for task in pending:
488+
task.cancel()
489+
loop.run_until_complete(
490+
asyncio.gather(*pending, return_exceptions=True)
491+
)
492+
loop.close()
468493

469494
thread = threading.Thread(target=run_proxy, daemon=True)
495+
proxy._thread = thread
470496
thread.start()
471497
time.sleep(1)
472498

tests/e2e/proxy/interception_proxy.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import json
2626
import logging
2727
import ssl
28+
import threading
2829
from pathlib import Path
2930
from typing import Any, Optional
3031

@@ -39,7 +40,7 @@
3940
IN_CLUSTER_CA_CERT_PATH = Path("/tmp/interception-proxy-ca.pem")
4041

4142

42-
class InterceptionProxy:
43+
class InterceptionProxy: # pylint: disable=too-many-instance-attributes
4344
"""Async TLS-intercepting proxy for testing.
4445
4546
Attributes:
@@ -64,6 +65,7 @@ def __init__(
6465
self.connect_count = 0
6566
self._server: Optional[asyncio.Server] = None
6667
self._handler_tasks: set[asyncio.Task[Any]] = set()
68+
self._thread: Optional[threading.Thread] = None
6769

6870
def _make_server_ssl_context(self, hostname: str) -> ssl.SSLContext:
6971
"""Create an SSL context with a certificate for the given hostname.

tests/e2e/proxy/tunnel_proxy.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import asyncio
2222
import json
2323
import logging
24+
import threading
2425
from typing import Any, Optional
2526

2627
# In-cluster defaults (``python tunnel_proxy.py``).
@@ -48,6 +49,7 @@ def __init__(self, host: str = "127.0.0.1", port: int = 8888) -> None:
4849
self.last_connect_target: Optional[str] = None
4950
self._server: Optional[asyncio.Server] = None
5051
self._handler_tasks: set[asyncio.Task[Any]] = set()
52+
self._thread: Optional[threading.Thread] = None
5153

5254
async def _handle_client(
5355
self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter

0 commit comments

Comments
 (0)