Skip to content

Artery test-mode: disarm the unknown-origin gate when the last blackhole heals - #8478

Merged
Aaronontheweb merged 2 commits into
devfrom
fix/artery-test-stage-blackhole-residue
Aug 26, 2026
Merged

Artery test-mode: disarm the unknown-origin gate when the last blackhole heals#8478
Aaronontheweb merged 2 commits into
devfrom
fix/artery-test-stage-blackhole-residue

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Member

Closes #8476.

Healing a blackhole removed the destination from its key's set but kept the (now empty) key in the map, so AnyBlackholePresent() stayed true for the rest of the run. While true, InboundTestStage drops every unknown-origin envelope except HandshakeReq - including HandshakeRsp - so a fresh incarnation of a peer (new uid = unknown origin) could be unable to complete a handshake after all blackholes were healed. That is precisely the shape of the restart specs in the multi-node suite: blackhole the victim, heal, victim restarts with a new uid.

The unknown-origin gate exists to keep mid-handshake traffic from sneaking past an active blackhole. Keeping it armed after the last heal serves no scenario the gate was built for, and breaks one that matters.

Fix: RemoveBlackhole drops a key once its destination set is empty, so AnyBlackholePresent() reflects whether any blackhole is actually active.

Tests: the two existing specs that asserted the residue as intended behavior are inverted to assert the corrected behavior (verified they catch a revert). New end-to-end spec in ArteryBlackholeEndToEndSpec: blackhole A-B over loopback TCP, heal, then a brand-new system C completes its handshake and exchanges traffic. All 255 Artery unit tests pass. Test-mode only; no production code path changes behavior.

PassThrough removed a healed pair from its destination set but kept
the (now empty) key in the map. AnyBlackholePresent() only checks
whether the map is empty, so once any blackhole was ever set it
stayed true for the rest of the process, even after every blackhole
was healed.

That flag gates InboundTestStage: while it is true, the inbound
stage drops every envelope from an unknown origin except a
HandshakeReq, including a HandshakeRsp. A peer that was never
blackholed, or a fresh incarnation of a healed peer, could get
silently stuck mid-handshake.

RemoveBlackhole now drops the key entirely once its destination set
is empty, so AnyBlackholePresent() reflects reality again.

Updated the existing SharedTestState and InboundTestStage unit specs
that had encoded the stale-residue behavior as expected, and added
an end-to-end spec: blackhole A<->B, heal it, then prove a brand-new
peer C completes its handshake and exchanges traffic.
@Aaronontheweb Aaronontheweb added akka-remote artery Akka.Remote Artery Protocol tests akka.net v1.6 Akka.NET v1.6-related issues labels Aug 26, 2026
@Aaronontheweb
Aaronontheweb merged commit f8bcfe5 into dev Aug 26, 2026
13 of 15 checks passed
@Aaronontheweb
Aaronontheweb deleted the fix/artery-test-stage-blackhole-residue branch August 26, 2026 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

akka.net v1.6 Akka.NET v1.6-related issues akka-remote artery Akka.Remote Artery Protocol tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Artery test-mode: healed blackholes leave the unknown-origin drop gate armed forever

1 participant