Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@catbro666
Copy link

@catbro666 catbro666 commented Oct 30, 2025

When peer.free is called from ngx_http_upstream_next 1, the state
argument is correctly passed. But for the last attempt that doesn't
finally enter ngx_http_upstream_next, peer.free is called from
ngx_http_upstream_finalize_request 2 with the state being 0, in this
case the last attempt is always considered successful. But in fact it
may  be unsuccessful. Therefore the status should also be checked there
in order to pass the correct state.

This PR checks status against u->conf->next_upstream and if it should be
considered unsuccessful, the state is set to NGX_PEER_FAILED before
peer.free is called.

Proposed changes

Describe the use case and detail of the change.

If this pull request addresses an issue on GitHub, make sure to reference that
issue using one of the
supported keywords.

Before creating a pull request, make sure to comply with the
Contributing Guidelines.

@catbro666 catbro666 force-pushed the fix/final-try-peer-free branch from 68fa437 to 6809708 Compare October 30, 2025 10:51
@catbro666 catbro666 marked this pull request as draft October 30, 2025 19:34
When `peer.free` is called from `ngx_http_upstream_next` [1], the `state`
argument is correctly passed. But for the last attempt that doesn't
finally enter `ngx_http_upstream_next`, `peer.free` is called from
`ngx_http_upstream_finalize_request` [2] with the `state` being 0, in this
case the last attempt is always considered successful. But in fact it
may  be unsuccessful. Therefore the status should also be checked there
in order to pass the correct `state`.

This PR checks status against `u->conf->next_upstream` and if it should be
considered unsuccessful, the `state` is set to `NGX_PEER_FAILED` before
`peer.free` is called.

[1]: https://github.com/nginx/nginx/blob/fd0848bdd3f7ed50a3a2cd5abe6bf4ae186927c6/src/http/ngx_http_upstream.c#L4565
[2]: https://github.com/nginx/nginx/blob/fd0848bdd3f7ed50a3a2cd5abe6bf4ae186927c6/src/http/ngx_http_upstream.c#L4748
@catbro666 catbro666 force-pushed the fix/final-try-peer-free branch from 6809708 to 4f1a151 Compare October 31, 2025 06:27
@catbro666 catbro666 marked this pull request as ready for review October 31, 2025 06:33
@arut
Copy link
Contributor

arut commented Nov 6, 2025

The last attempt is also handled in ngx_http_upstream_next(). The code that triggers a next upstream condition does not know if it's the last peer. As for all other (non-next-upstream) errors, they are not considered unsuccessful attempts.

@arut arut closed this Nov 6, 2025
@catbro666
Copy link
Author

The last attempt is also handled in ngx_http_upstream_next(). The code that triggers a next upstream condition does not know if it's the last peer. As for all other (non-next-upstream) errors, they are not considered unsuccessful attempts.

@arut The last attempt does not always enter ngx_http_upstream_next(). For the cases of error, timeout, invalid_header, it does handled in ngx_http_upstream_next(). For other cases (http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 ), it's handled by ngx_http_upstream_test_next. Please see this code snippet in ngx_http_upstream_test_next. If the current attempt is the last attempt (i.e. u->peer.tries <= 1), it won't call ngx_http_upstream_next even though the error type is actually included in next_upstream. And eventually the peer will be freed here with the state being 0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants