openwisp / openwisp/openwisp-controller

[bug] SSH connection leaked when update_config() raises an exception

Open
#1,306 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
773
Forks
315
Avg merge
2d 16h
Merged PRs (30d)
14

Description

● 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

  1. Set up a device with an SSH DeviceConnection
  2. Make the config push fail intentionally (e.g. wrong credentials, unreachable device, or network drop mid-transfer)
  3. Observe that no disconnect() is called — the SSH session stays open
  4. 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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in openwisp_controller/connection/base/models.py around lines 365–373 and read the DeviceConnection.update_config() flow. Reproduce a failed config push, then verify the SSH connection is disconnected on both successful and exceptional completion without leaving file descriptors open.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, networking
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.