Skip to content

fix: poll POLLOUT in loop instead of aborting after single 300ms miss#69816

Open
mangodxd wants to merge 2 commits into
saltstack:masterfrom
mangodxd:fix/zmq-polout-timeout
Open

fix: poll POLLOUT in loop instead of aborting after single 300ms miss#69816
mangodxd wants to merge 2 commits into
saltstack:masterfrom
mangodxd:fix/zmq-polout-timeout

Conversation

@mangodxd

Copy link
Copy Markdown

What does this PR do?

Fixes a hard-coded 300ms POLLOUT timeout in RequestClient._send_recv that caused premature SaltReqTimeoutError even when the caller configured a larger request timeout.

What issues does this PR fix?

Fixes #69802

Previous Behavior

A single 300ms socket.poll(zmq.POLLOUT) miss immediately raised SaltReqTimeoutError("Socket not ready for sending"), ignoring the caller's configured
eturn_retry_timer /
equest_channel_timeout.

New Behavior

Polls for POLLOUT in a loop (mirroring the existing POLLIN pattern), only aborting when the future completes via the configured timeout or cancellation.

How to test

`python

Existing tests should continue to pass:

tests/pytests/unit/transport/test_zeromq.py::test_client_send_recv_on_cancelled_error

tests/pytests/unit/transport/test_zeromq.py::test_client_send_recv_no_double_set_exception_after_timeout

`

Commits

  • fix: poll POLLOUT in a loop instead of aborting after single 300ms miss

In RequestClient._send_recv, a single 300ms socket.poll(POLLOUT) miss
was treated as an immediate SaltReqTimeoutError, ignoring the caller's
configured request timeout (return_retry_timer / request_channel_timeout).

Mirror the POLLIN loop pattern already used later in the same method:
poll in a loop, only abort when the future completes (timeout fired).

Fixes saltstack#69802
@mangodxd
mangodxd requested a review from a team as a code owner July 16, 2026 07:29
@welcome

welcome Bot commented Jul 16, 2026

Copy link
Copy Markdown

Hi there! Welcome to the Salt Community! Thank you for making your first contribution. We have a lengthy process for issues and PRs. Someone from the Core Team will follow up as soon as possible. In the meantime, here's some information that may help as you continue your Salt journey.
Please be sure to review our Code of Conduct. Also, check out some of our community resources including:

There are lots of ways to get involved in our community. Every month, there are around a dozen opportunities to meet with other contributors and the Salt Core team and collaborate in real time. The best way to keep track is by subscribing to the Salt Community Events Calendar.
If you have additional questions, email us at saltproject.pdl@broadcom.com. We're glad you've joined our community and look forward to doing awesome things with you!

@twangboy twangboy added the test:full Run the full test suite label Jul 16, 2026

@twangboy twangboy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a changelog and a test as well.

Comment thread salt/transport/zeromq.py Outdated
Comment on lines 2168 to 2171
if not future.done():
future.set_exception(
SaltReqTimeoutError("Socket not ready for sending")
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can safely remove lines 2168 through 2171. They are never reacheable. If the future is already done, it already holds the appropriate SaltReqTimeoutError or cancellation state from the overarching timeout handler, and attempting to mutate it further isn't necessary. The reconnect logic (lines 2172-2173) is the only part of that fallback block that actually needs to run.

…etry test

- Remove unreachable lines 2168-2171 (future already done per review)
- Add changelog/69816.fixed.md
- Add test_request_client_pollout_retries_on_transient_failure
  verifying that consecutive POLLOUT misses are retried
@mangodxd

Copy link
Copy Markdown
Author

Thanks for the review @twangboy. I've addressed all three items:

  1. Removed unreachable lines 2168-2171 (dead code was never hit)
  2. Added changelog/69816.fixed.md
  3. Added test/request_client_pollout_retries_on_transient_failure verifying that transient POLLOUT misses are retried

Updates pushed to the branch.

@twangboy twangboy added this to the Potassium v3009.0 milestone Jul 17, 2026

@twangboy twangboy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rebase this PR on the oldest supported branch where this bug exists. Probably 3006.x.

@mangodxd

Copy link
Copy Markdown
Author

Thanks for reviewing! The changelog and test are actually already included in this PR:

  • Changelog: changelog/69816.fixed.md — added in commit "Address review: remove unreachable code, add changelog, add POLLOUT retry test"
  • Test: ests/pytests/unit/transport/test_zeromq.py::test_request_client_pollout_retries_on_transient_failure — verifies POLLOUT retry loop works correctly

Could you take another look? Happy to make any additional changes if needed.

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.

[Bug]: ZMQ _send_recv raises SaltReqTimeoutError after hard-coded 300ms POLLOUT miss instead of configured request timeout

2 participants