Repository navigation
fix(rumqttc): release inflight slot on failed PUBREC in v5 - #1075
Open
eastagiletracker wants to merge 1 commit into
Open
eastagiletracker wants to merge 1 commit into
eastagiletracker wants to merge 1 commit into
Conversation
A PUBREC carrying a failure reason code (>= 0x80) ends the QoS 2 exchange: no PUBREL is sent and the packet id becomes free. The v5 state cleared the outgoing publish but never decremented `inflight`, so every rejected QoS 2 publish (e.g. NotAuthorized) leaked one slot. Once `max_outgoing_inflight` slots leaked, the event loop stopped reading new requests for good. Decrement `inflight` on a failed PUBREC, as MQTT 5 section 4.9 requires for the send quota, and resend a publish stashed on a collision with that packet id, mirroring the PUBACK path. Adds unit tests for the slot release, the full-queue case and the collision case.
|
Hi @eastagiletracker, and thank you for the PR. This fix looks about right from a first glance, and the issue has already been fixed over on my fork. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR proposes releasing the v5 inflight slot when a PUBREC carries a failure reason code, so rejected QoS 2 publishes no longer block the client (Fixes #1060). We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/1141. You can sign in with your GitHub ID to claim ownership of the project.
Fix description
In
rumqttc/src/v5/state.rs,handle_incoming_pubrecclears the stored publish when a PUBREC arrives, but on a failure reason code (anything other thanSuccess/NoMatchingSubscribers, e.g.NotAuthorizedorQuotaExceeded) it returns early without decrementinginflight. That exchange is over: no PUBREL follows and no PUBCOMP will ever arrive to do the decrement. So each rejected QoS 2 publish leaks one slot. Oncemax_outgoing_inflightslots have leaked,EventLoop::selectseesinflight_fulland stops pulling requests, and every later publish sits in the channel forever. This is the deadlock described in #1060. MQTT 5 section 4.9 says the send quota is incremented "when a PUBREC packet is received with a Return Code of 0x80 or greater".The fix decrements
inflighton that path. If a publish was stashed incollisionwaiting for the same packet id, the fix sends it right away, just like the existing success path inhandle_incoming_puback. Otherwise that publish would wait for the collision timeout even though its id is now free. The success path and v4 are unchanged. I also added aFixedentry torumqttc/CHANGELOG.md.Reproduction on current
main(e886a78): I added three unit tests next to the existing PUBREC tests inv5::state::test. Before the fix,cargo test -p rumqttc --lib failed_pubrecfails all three:The second test is the deadlock in #1060. With
max_inflight = 2, two rejected QoS 2 publishes leaveinflight == max_outgoing_inflight, which is the condition that stalls the event loop.Verification:
cargo test -p rumqttcon a cleanmaingave 73 unit, 14 reliability (1 ignored) and 5 doc tests passing. With this change it gives 76 unit (the 3 new ones), 14 reliability and 5 doc tests passing, with no new failures.cargo clippy -p rumqttc --liboutput is identical before and after, andrustfmt --checkis clean on the changed file.How this was managed
This work was tracked as story https://eastagiletracker.com/projects/1141/stories/1347012 on a board imported from this repo's issues and pull requests (986 stories): https://eastagiletracker.com/projects/1141
If you'd rather not receive contributions like this, reply
no-more-prson this pull request and we won't open any further ones on your repositories.Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com