Skip to content

Close connections after incomplete ASCII and admin operations - #93

Merged
mrattle merged 6 commits into
mainfrom
cancellation-safety-all-entry-points
Oct 19, 2026
Merged

mrattle merged 6 commits into
mainfrom
cancellation-safety-all-entry-points

Conversation

@sam-obeid

@sam-obeid sam-obeid commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

What

Extends #91's OperationGuard from the meta commands to every entry point, so cancelling or failing any operation mid-response closes the connection instead of leaving a stale reply for the next request.

Changes

  • All entry points guarded: every AsciiProtocol method (and _no_reply variants), plus version, stats, flush_all and dump_keys. Key validation stays before the guard, so KeyTooLong leaves the connection usable.
  • EOF in version / flush_all: a server closing mid-reply now returns Io(UnexpectedEof) and closes the client, like every other entry point (previously a protocol error with is_closed() == false).
  • Leaked operations: an operation or MetadumpIter skipped with mem::forget / Box::leak no longer lets its unread reply answer the next request. is_closed() reports it, and the next call closes the connection and returns ConnectionClosed.
  • MetadumpIter:
    • Owns its guard: dropping it before END closes the connection immediately.
    • Every Some(Err(_)) is terminal (including BUSY); new is_complete() tells a finished dump from one cut short.
    • Parses current memcached 1.6 entries (flags= and a trailing space after size); a non-empty cache previously failed to dump.
  • CHANGELOG: upgrade notes for Error::ConnectionClosed (from Close connections after incomplete meta operations #91).

Breaking changes

  • MetadumpIter keeps the Client mutably borrowed until it is dropped, even after next() returns None. Drain-then-reuse in the same scope now fails with E0499; drop the iterator or end its scope first (as tests/client_integration_tests.rs now does with drop(dump)).
  • Error::ConnectionClosed (from Close connections after incomplete meta operations #91): treat it like Io and discard the client; check is_closed() in pool recycle / has_broken.

Cut the next release as 0.9.0 after this lands.

Testing

New tests in tests/cancellation_safety.rs cover cancellation, EOF, leaks and metadump termination for each entry point; a new real-server test dumps a populated cache. scripts/test-integration.sh, cargo fmt --check and cargo clippy --all-targets --all-features -- -D warnings pass.

@sam-obeid
sam-obeid requested a review from a team as a code owner September 23, 2026 19:32
@mrattle
mrattle force-pushed the c1-cancellation-safety branch 3 times, most recently from d4aa8b1 to 17e1420 Compare September 24, 2026 16:17
@mrattle
mrattle force-pushed the cancellation-safety-all-entry-points branch from feba5b0 to e4ea568 Compare October 16, 2026 17:20
@mrattle
mrattle force-pushed the c1-cancellation-safety branch from 17e1420 to c527407 Compare October 16, 2026 17:20
sam-obeid and others added 2 commits October 16, 2026 13:51
Extend the fake-server suite from the seven meta operations to all 25
public entry points. Each replying ASCII command, plus version, stats,
flush_all and dump_keys, is cancelled between request and response and
must leave the client closed; a closed client must refuse every entry
point without touching the socket; completed operations, fully read
refusals, no-reply commands, key-length rejections and unpolled futures
must all leave the connection open and in sync.

The metadump iterator gets its own cases: dropping it mid-dump closes
the connection, END/BADCLASS/BUSY end the iterator and keep the
connection, and cancelling a single next() call leaves the partially
read entry buffered for the following call.

Seven of these tests fail on purpose until the guard is extended; the
next commit turns them green.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PR #91 introduced OperationGuard for the meta commands only. The ASCII
commands and the client-level version, stats, flush_all and dump_keys
still wrote a request and read the reply with nothing marking the
connection unusable if the future was dropped in between, so the stale
reply became the answer to the next request on that connection.

Wrap all 18 remaining entry points in the same guard, following the
rule already used by the meta commands: validate key length before
starting the operation so a rejected key sends nothing and keeps the
connection; complete the guard after the last read and before matching
the response so fully read refusals and error lines never close it;
for no-reply commands, complete right after flush.

MetadumpIter now owns the guard as an Option. END, BADCLASS and BUSY
complete it and end the iterator, so a refusal leaves the connection
usable; a network or protocol error, or dropping the iterator before
END, drops the guard uncompleted and closes the connection. BUSY was
previously non-terminal and re-read the socket on every next() call.

The ASCII module reuses the crate-level MAX_KEY_LENGTH instead of a
duplicate constant. Doc comments and the changelog no longer say the
close applies to meta operations only.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@mrattle
mrattle changed the base branch from c1-cancellation-safety to main October 16, 2026 17:51
@mrattle
mrattle force-pushed the cancellation-safety-all-entry-points branch from e4ea568 to 58e390b Compare October 17, 2026 18:41
@mrattle mrattle self-assigned this Oct 19, 2026

@mrattle mrattle 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.

Original changes looked good, patches were tested through staging and behave as expected.

@mrattle
mrattle merged commit 404d816 into main Oct 19, 2026
3 of 4 checks passed
@mrattle mrattle mentioned this pull request Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants