-
Notifications
You must be signed in to change notification settings - Fork 96
Description
Bug Description
AGFSManager._check_port_available() (openviking/agfs_manager.py lines 113–123) creates a socket but only closes it on the success path. When sock.bind() raises OSError (port already in use), the code raises RuntimeError without ever closing the socket, leaking a file descriptor.
def _check_port_available(self) -> None:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.bind(("localhost", self.port))
sock.close() # Only reached on success
except OSError as e:
raise RuntimeError( # sock is never closed here
f"AGFS port {self.port} is already in use..."
) from eSteps to Reproduce
import socket
from openviking.agfs_manager import AGFSManager
# Occupy a port
blocker = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
blocker.bind(("localhost", 19998))
blocker.listen(1)
# Call _check_port_available on the occupied port
mgr = AGFSManager.__new__(AGFSManager)
mgr.port = 19998
try:
mgr._check_port_available()
except RuntimeError:
pass # Socket fd leaked here
blocker.close()Expected Behavior
The socket should be closed on both success and failure paths, e.g. using finally: sock.close().
Actual Behavior
Python emits a ResourceWarning confirming the socket was never closed:
Exception ignored in: <socket.socket fd=664, family=2, type=1, proto=0>
ResourceWarning: unclosed <socket.socket fd=664, family=2, type=1, proto=0>
Each failed call leaks one file descriptor.
Minimal Reproducible Example
import socket
import warnings
warnings.simplefilter("error", ResourceWarning)
from openviking.agfs_manager import AGFSManager
blocker = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
blocker.bind(("localhost", 19998))
blocker.listen(1)
mgr = AGFSManager.__new__(AGFSManager)
mgr.port = 19998
try:
mgr._check_port_available()
except RuntimeError:
pass
import gc
gc.collect()
# ResourceWarning: unclosed <socket.socket fd=664, ...>
blocker.close()Error Logs
Exception ignored in: <socket.socket fd=664, family=2, type=1, proto=0>
ResourceWarning: unclosed <socket.socket fd=664, family=2, type=1, proto=0>OpenViking Version
0.1.10 (main branch, 2026-02-07)
Python Version
3.13.7
Operating System
Windows
Model Backend
Other
Additional Context
Fix is straightforward — move sock.close() into a finally block:
def _check_port_available(self) -> None:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.bind(("localhost", self.port))
except OSError as e:
raise RuntimeError(
f"AGFS port {self.port} is already in use..."
) from e
finally:
sock.close()In retry scenarios or test suites where _check_port_available is called repeatedly with an occupied port, this leak can accumulate and eventually exhaust file descriptors.