● Describe the bug
In DeviceConnection.update_config(), the SSH connection is only closed
in the else block, which means it is never disconnected when an
exception occurs during a config push. Over time this leaks SSH file
descriptors and can crash the controller process with:
OSError: [Errno 24] Too many open files
● Steps To Reproduce
- Set up a device with an SSH
DeviceConnection
- Make the config push fail intentionally (e.g. wrong credentials, unreachable device, or network drop mid-transfer)
- Observe that no
disconnect() is called — the SSH session stays open
- Repeat for multiple devices; file descriptor count keeps growing
● Root cause (file + line)
File: openwisp_controller/connection/base/models.py
Lines: 365–373
def update_config(self):
self.connect()
if self.is_working:
try:
self.connector_instance.update_config()
except Exception as e:
logger.exception(e)
else:
self.disconnect() # ← only runs when NO exception is raised
The else block in a try/except/else only executes when the try
block completes without raising. Any exception causes disconnect()
to be skipped entirely.
● Expected behavior
The SSH connection should always be closed after update_config()
completes — whether it succeeded or failed — to prevent file descriptor
leaks on production controllers.
● Proposed fix
Change else to finally:
def update_config(self):
self.connect()
if self.is_working:
try:
self.connector_instance.update_config()
except Exception as e:
logger.exception(e)
finally:
self.disconnect() # ← runs always, success OR failure
● Screenshots
Not applicable (code-level bug).
● System Information
- OS: Ubuntu 24.04 LTS
- Python Version: Python 3.10+
- Django Version: Django 4.2+
- Browser and Browser Version (if applicable): Not applicable
● Describe the bug
In
DeviceConnection.update_config(), the SSH connection is only closedin the
elseblock, which means it is never disconnected when anexception occurs during a config push. Over time this leaks SSH file
descriptors and can crash the controller process with:
● Steps To Reproduce
DeviceConnectiondisconnect()is called — the SSH session stays open● Root cause (file + line)
File:
openwisp_controller/connection/base/models.pyLines: 365–373
The
elseblock in atry/except/elseonly executes when thetryblock completes without raising. Any exception causes
disconnect()to be skipped entirely.
● Expected behavior
The SSH connection should always be closed after
update_config()completes — whether it succeeded or failed — to prevent file descriptor
leaks on production controllers.
● Proposed fix
Change
elsetofinally:● Screenshots
Not applicable (code-level bug).
● System Information