Skip to content

fix(broker): cancel zombie coroutine and reset connection on execute timeout (#925) - #950

Open
oboehmer wants to merge 1 commit into
mainfrom
fix/925-cancel-zombie-coroutine-on-timeout
Open

oboehmer wants to merge 1 commit into
mainfrom
fix/925-cancel-zombie-coroutine-on-timeout

Conversation

@oboehmer

Copy link
Copy Markdown
Collaborator

Description

Cancels the underlying asyncio coroutine when future.result(timeout=DEVICE_EXECUTE_TIMEOUT) times out in SSHTestBase._patch_device_execute_for_broker(), and ensures BrokerClient tears down the socket connection on cancellation to prevent zombie coroutines from blocking subsequent broker commands or reusing a desynchronized socket stream.

Closes

Related Issue(s)

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactoring / Technical debt (internal improvements with no user-facing changes)
  • Documentation update
  • Chore (build process, CI, tooling, dependencies)
  • Other (please describe):

Test Framework Affected

  • PyATS
  • Robot Framework
  • Both
  • N/A (not test-framework specific)

Network as Code (NaC) Architecture Affected

  • ACI (APIC)
  • NDO (Nexus Dashboard Orchestrator)
  • NDFC / VXLAN-EVPN (Nexus Dashboard Fabric Controller)
  • Catalyst SD-WAN (SDWAN Manager / vManage)
  • Catalyst Center (DNA Center)
  • ISE (Identity Services Engine)
  • FMC (Firepower Management Center)
  • Meraki (Cloud-managed)
  • NX-OS (Nexus Direct-to-Device)
  • IOS-XE (Direct-to-Device)
  • IOS-XR (Direct-to-Device)
  • Hyperfabric
  • All architectures
  • N/A (architecture-agnostic)

Platform Tested

nac-test supports macOS and Linux only

  • macOS (version tested: Darwin 25.3.0 / macOS 15)
  • Linux (distro/version tested: )

Key Changes

  • In ssh_base_test.py: Catch TimeoutError on future.result(timeout=DEVICE_EXECUTE_TIMEOUT) and invoke future.cancel() to cancel the underlying task on the event loop.
  • In broker_client.py: Catch asyncio.CancelledError in _send_request and call self._teardown_connection() so the cancelled in-flight socket stream is cleanly reset and cannot corrupt or stall the next command.
  • In test_ssh_base_test.py: Added assertion that mock_future.cancel() is called on timeout.
  • In test_connection_broker.py: Added TestBrokerClientCancellation verifying that a cancelled hanging request tears down the connection and enables subsequent commands on the client to reconnect and succeed without queueing or errors.

Testing Done

  • Unit tests added/updated
  • Integration tests performed
  • Manual testing performed:
    • PyATS tests executed successfully
    • Robot Framework tests executed successfully
    • D2D/SSH tests executed successfully (if applicable)
    • HTML reports generated correctly
  • All existing tests pass (pytest / pre-commit run -a)

Test Commands Used

pytest tests/unit/pyats_core/
pre-commit run -a

Checklist

  • Code follows project style guidelines (pre-commit run -a passes)
  • Self-review of code completed
  • Code is commented where necessary (especially complex logic)
  • Documentation updated (if applicable)
  • No new warnings introduced
  • Changes work on both macOS and Linux
  • CHANGELOG.md updated (if applicable)

Screenshots (if applicable)

N/A

Additional Notes

None

@oboehmer oboehmer added the bug Something isn't working label Sep 11, 2026
@oboehmer
oboehmer requested review from ChristopherJHart and aitestino and removed request for ChristopherJHart September 11, 2026 13:42
@oboehmer oboehmer self-assigned this Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cancel zombie coroutine on broker future.result() timeout (or serialize broker requests)

1 participant