Problem
The NetworkManager pre-down path treats the same retryable suspend-rail result differently depending on which source acquired the rail first.
When logind already owns the cycle, NetworkManager joins it, observes RetryableTransportFailure, and performs one follow-up attempt before releasing network teardown. When NetworkManager itself owns the cycle and its first attempt produces SuspendRailDisposition::RetryableFailure, handle_network_teardown_rail_disposition returns immediately because its retry branch only handles JoinedInProgress.
The result is a source-ordering asymmetry: an otherwise recoverable first transport failure gets a second opportunity in the logind-first ordering, but not in the NetworkManager-first ordering.
Confirmed reproduction
Reproduced deterministically against dev commit 857535aa0ef6b669b670656ffedb3417fb454239 with this sequence:
- logind reports
PreparingForSleep=true;
- NetworkManager acquires the empty suspend rail as owner;
- the configured TV input matches;
- the first
power_off attempt returns a retryable transport failure;
- a second attempt would succeed.
A regression test expecting the cycle to complete currently fails with:
left: Some(RetryableTransportFailure)
right: Some(Completed)
Only one power_off attempt is made, no system ownership marker is created, and NetworkManager releases teardown.
Expected behavior
An NM-owned RetryableFailure should receive the same single follow-up opportunity that already exists when NetworkManager joins a logind-owned retryable cycle. Retry eligibility must not depend on which event source happened to acquire the rail first.
Acceptance criteria
- Add a regression test for an NM-owned cycle whose first retryable transport failure is followed by a successful attempt.
- Make exactly one follow-up attempt before releasing NetworkManager teardown.
- Record
Completed and create the system ownership marker when the follow-up succeeds.
- Release teardown after the follow-up fails; do not introduce an unbounded retry loop.
- Preserve existing behavior for authentication failures, non-retryable outcomes, completed cycles, duplicate events, disabled policy, and ordinary network disconnects.
- Keep the existing joined-owner retry test passing.
Scope
This issue is limited to making the existing suspend-rail retry opportunity source-independent.
It does not introduce or require:
- a long-lived TV actor or persistent WebSocket;
- IPC or lifecycle service ownership changes;
- a new global deadline model;
- a redesign of transport-delivery or ambiguous-effect semantics;
- additional retries beyond the existing single follow-up opportunity;
- NetworkManager route retention, NIC Wake-on-LAN configuration, or topology detection;
- changes to TV platform selection or pairing behavior.
Future hardening may refine which transport outcomes qualify as retryable. That refinement should remain compatible with the source-independent rail behavior established here.
Problem
The NetworkManager
pre-downpath treats the same retryable suspend-rail result differently depending on which source acquired the rail first.When logind already owns the cycle, NetworkManager joins it, observes
RetryableTransportFailure, and performs one follow-up attempt before releasing network teardown. When NetworkManager itself owns the cycle and its first attempt producesSuspendRailDisposition::RetryableFailure,handle_network_teardown_rail_dispositionreturns immediately because its retry branch only handlesJoinedInProgress.The result is a source-ordering asymmetry: an otherwise recoverable first transport failure gets a second opportunity in the logind-first ordering, but not in the NetworkManager-first ordering.
Confirmed reproduction
Reproduced deterministically against
devcommit857535aa0ef6b669b670656ffedb3417fb454239with this sequence:PreparingForSleep=true;power_offattempt returns a retryable transport failure;A regression test expecting the cycle to complete currently fails with:
Only one
power_offattempt is made, no system ownership marker is created, and NetworkManager releases teardown.Expected behavior
An NM-owned
RetryableFailureshould receive the same single follow-up opportunity that already exists when NetworkManager joins a logind-owned retryable cycle. Retry eligibility must not depend on which event source happened to acquire the rail first.Acceptance criteria
Completedand create the system ownership marker when the follow-up succeeds.Scope
This issue is limited to making the existing suspend-rail retry opportunity source-independent.
It does not introduce or require:
Future hardening may refine which transport outcomes qualify as retryable. That refinement should remain compatible with the source-independent rail behavior established here.