Skip to content

Fix HighState/State leaking fileclient on init failure (#69637)#69675

Merged
dwoz merged 1 commit into
saltstack:3006.xfrom
dwoz:fix/issue-69637
Jul 6, 2026
Merged

Fix HighState/State leaking fileclient on init failure (#69637)#69675
dwoz merged 1 commit into
saltstack:3006.xfrom
dwoz:fix/issue-69637

Conversation

@dwoz

@dwoz dwoz commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Fix HighState.__init__ and State.__init__ leaking their fileclient (and its ZeroMQ transport) when a later step in the constructor raises. The salt-call flow that hits the failure now shuts down cleanly instead of emitting TransportWarning: Unclosed transport! at interpreter exit.

What issues does this PR fix or reference?

Fixes #69637

Previous Behavior

salt-call state.apply on 3006.26/3006.27 prints repeated TransportWarning: Unclosed transport! <salt.transport.zeromq.RequestClient> messages, with a stack pointing at HighState.__init__ -> get_file_client -> RemoteClient.__init__. This is the warning added by PR #65559.

New Behavior

Both HighState.__init__ and State.__init__ wrap their post-get_file_client bodies in try/except and call .destroy() on the freshly-allocated fileclient before re-raising, so the ZeroMQ transport is torn down cleanly and Transport.__del__ no longer trips the warning. State._gather_pillar() also destroys the temporary Pillar in a try/finally so its channel doesn't rely on __del__ ordering at shutdown.

Merge requirements satisfied?

  • Docs (no user-facing docs change; behavior fix only)
  • Changelog (changelog/69637.fixed.md)
  • Tests written/updated (tests/pytests/unit/state/test_highstate_transport_cleanup.py)

Commits signed with GPG?

Yes

When ``HighState.__init__`` or ``State.__init__`` raised after allocating
their fileclient (e.g. ``BaseHighState.__init__`` failing during
``master_opts()``, or ``_gather_pillar()`` failing during pillar
compilation), the caller never received the instance and therefore never
called ``.destroy()``.  The fileclient's ZeroMQ ``RequestClient`` was
finalized during garbage collection with ``_closing = False``, tripping
the ``TransportWarning: Unclosed transport!`` warning that PR saltstack#65559
added.

Wrap both constructors' post-allocation bodies in ``try/except`` that
destroys the freshly-allocated fileclient before re-raising.  Also close
the temporary ``Pillar`` object built by ``State._gather_pillar()`` in a
``try/finally`` so its channel doesn't rely on ``__del__`` ordering at
shutdown.

Fixes saltstack#69637
@dwoz
dwoz merged commit cb09894 into saltstack:3006.x Jul 6, 2026
863 of 870 checks passed
dwoz added a commit that referenced this pull request Jul 23, 2026
When HighState.__init__ or State.__init__ raised after allocating
their fileclient (e.g. BaseHighState.__init__ failing during
master_opts(), or _gather_pillar() failing during pillar
compilation), the caller never received the instance and therefore
never called .destroy().  The fileclient's ZeroMQ RequestClient
was finalized during garbage collection with _closing = False,
tripping the ``TransportWarning: Unclosed transport!`` warning
that PR #65559 added.

Wrap both constructors' post-allocation bodies in try/except that
destroys the freshly-allocated fileclient before re-raising.  Also
close the temporary Pillar object built by State._gather_pillar()
in a try/finally so its channel doesn't rely on __del__ ordering
at shutdown.

Backport of cb09894 from PR #69675.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:full Run the full test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants