Skip to content

Fix serial fd leak in SerialConnection.connect() on timeout - #101

Open
joeyleake wants to merge 1 commit into
meshcore-dev:mainfrom
joeyleake:fix/95-serial-fd-leak-on-timeout
Open

Fix serial fd leak in SerialConnection.connect() on timeout#101
joeyleake wants to merge 1 commit into
meshcore-dev:mainfrom
joeyleake:fix/95-serial-fd-leak-on-timeout

Conversation

@joeyleake

Copy link
Copy Markdown

Fixes #95

Problem

SerialConnection.connect() leaked 3 file descriptors (the serial port fd
plus two internal pipe fds) every time a connection attempt timed out.
In a reconnect loop against an unresponsive device, this exhausts the
~1024 fd limit and starts failing with "Too many open files".

Root cause

serial_asyncio.create_serial_connection() opens the fds immediately, but
the transport was only ever captured via self.transport, which is
assigned inside MCSerialClientProtocol.connection_made() — an async
callback. If asyncio.wait_for(self._connected_event.wait(), ...) timed
out before connection_made() ran, self.transport stayed None, so there
was no way to close the already-opened transport. It was simply
abandoned.

Fix

connect() now captures transport directly from create_serial_connection()'s
own return value instead of relying on self.transport being set. If the
subsequent wait_for() raises for any reason (timeout or otherwise), the
transport is closed before re-raising. Added a narrow guard
(if self.transport is transport: self.transport = None) for the case
where connection_made() fires right at the timeout boundary, so closing
this attempt's transport never clobbers self.transport if it's already
pointing at a different, unrelated connection. The success path
(logging + return self.port) is unchanged.

Testing

Added tests/unit/test_serial_connection.py::test_connect_closes_transport_on_timeout,
which patches create_serial_connection to return a transport whose
connection_made() never fires, and asserts transport.close() is called
before the TimeoutError propagates.

Full suite: 180 passed, 2 failed (test_send_cmd,
test_advert_path_preserves_embedded_zero_bytes) — both pre-existing on a
clean main checkout, unrelated to this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Serial fd leak in SerialConnection.connect() when connection times out

1 participant