From b8772426371b17cef96770afbbfdb570cf8c03c6 Mon Sep 17 00:00:00 2001 From: Clinton Thomas <1033162+KernelClint@users.noreply.github.com> Date: Tue, 1 Sep 2026 13:29:01 -0400 Subject: [PATCH 1/2] automaton: drop stopped children from the spawn listener AI-Assisted: yes (GPT-5.6-Cyber) --- scapy/automaton.py | 3 ++- test/scapy/automaton.uts | 46 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/scapy/automaton.py b/scapy/automaton.py index 5f3ffcc12cd..f26370b102f 100644 --- a/scapy/automaton.py +++ b/scapy/automaton.py @@ -1042,9 +1042,10 @@ def _run() -> None: # start atmt atmt_server.runbg() # housekeeping - for atmt, clientsocket in clients: + for atmt, clientsocket in clients[:]: if not atmt.isrunning(): atmt.destroy() + clients.remove((atmt, clientsocket)) except KeyboardInterrupt: print("X Exiting.") ssock.shutdown(socket.SHUT_RDWR) diff --git a/test/scapy/automaton.uts b/test/scapy/automaton.uts index ab107b8bc74..c53018333c8 100644 --- a/test/scapy/automaton.uts +++ b/test/scapy/automaton.uts @@ -352,6 +352,51 @@ r = x r assert r == "Venus" += Spawn removes stopped connection children during housekeeping + +def stopped_spawn_children_are_removed(): + import socket + import time + class QuickConnection: + socketcls = None + pkt_cls = None + created = 0 + destroy_calls = 0 + def __init__(self, sock, **kwargs): + type(self).created += 1 + self.running = True + def runbg(self): + self.running = False + def isrunning(self): + return self.running + def destroy(self): + type(self).destroy_calls += 1 + def forcestop(self, wait=False): + self.running = False + QuickConnection.spawn = classmethod(Automaton.spawn.__func__) + listener = QuickConnection.spawn( + 0, + local_ip="127.0.0.1", + bg=True, + verb=False, + ) + try: + for expected in range(1, 5): + client = socket.create_connection(listener.getsockname(), timeout=1) + client.close() + deadline = time.monotonic() + 1 + while QuickConnection.created < expected and time.monotonic() < deadline: + time.sleep(0.001) + return QuickConnection.destroy_calls == QuickConnection.created + finally: + try: + listener.shutdown(socket.SHUT_RDWR) + except OSError: + pass + listener.close() + +assert stopped_spawn_children_are_removed() + = Automaton timer function ~ run timers @@ -519,4 +564,3 @@ if LINUX: if LINUX: # Remove the iptables rule assert os.system(IPTABLE_RULE % ('D', SECDEV_IP4)) == 0 - From 525a136804cec8e5d8f40479fd556992f1c0aaef Mon Sep 17 00:00:00 2001 From: Gabriel <10530980+gpotter2@users.noreply.github.com> Date: Thu, 3 Sep 2026 21:25:18 +0200 Subject: [PATCH 2/2] Apply suggestion from @gpotter2 --- test/scapy/automaton.uts | 45 ---------------------------------------- 1 file changed, 45 deletions(-) diff --git a/test/scapy/automaton.uts b/test/scapy/automaton.uts index c53018333c8..6aec9b0bbac 100644 --- a/test/scapy/automaton.uts +++ b/test/scapy/automaton.uts @@ -352,51 +352,6 @@ r = x r assert r == "Venus" -= Spawn removes stopped connection children during housekeeping - -def stopped_spawn_children_are_removed(): - import socket - import time - class QuickConnection: - socketcls = None - pkt_cls = None - created = 0 - destroy_calls = 0 - def __init__(self, sock, **kwargs): - type(self).created += 1 - self.running = True - def runbg(self): - self.running = False - def isrunning(self): - return self.running - def destroy(self): - type(self).destroy_calls += 1 - def forcestop(self, wait=False): - self.running = False - QuickConnection.spawn = classmethod(Automaton.spawn.__func__) - listener = QuickConnection.spawn( - 0, - local_ip="127.0.0.1", - bg=True, - verb=False, - ) - try: - for expected in range(1, 5): - client = socket.create_connection(listener.getsockname(), timeout=1) - client.close() - deadline = time.monotonic() + 1 - while QuickConnection.created < expected and time.monotonic() < deadline: - time.sleep(0.001) - return QuickConnection.destroy_calls == QuickConnection.created - finally: - try: - listener.shutdown(socket.SHUT_RDWR) - except OSError: - pass - listener.close() - -assert stopped_spawn_children_are_removed() - = Automaton timer function ~ run timers