Skip to content

Keep the network listener active after callback fallback - #141

Merged
hawkff merged 1 commit into
mainfrom
fix/007-network-listener-fallback
Jul 12, 2026
Merged

Keep the network listener active after callback fallback#141
hawkff merged 1 commit into
mainfrom
fix/007-network-listener-fallback

Conversation

@hawkff

@hawkff hawkff commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • track callback registration success explicitly
  • skip invalid unregister calls after fallback
  • contain unregister failures and test state transitions

Validation

  • Namespace CI run 29210564463 passed
  • local read-only review reported no findings

Greptile Summary

This PR keeps the network listener usable when callback unregister or register calls fail. The main changes are:

  • Added a small registration state helper for callback lifecycle tracking.
  • Added fallback delivery of the current active network on listener start.
  • Wrapped unregister failures so later cleanup can be retried.
  • Added unit tests for registration and unregister failure transitions.

Confidence Score: 4/5

This is close, but the fallback recovery path should be fixed before merging.

  • A repeated unregister cleanup failure can leave the listener without ongoing network-change callbacks.
  • New listeners get one current network value, but later network changes can be missed.
  • The helper state transitions and tests look consistent outside that recovery path.

app/src/main/java/io/nekohasekai/sagernet/utils/DefaultNetworkListener.kt

Important Files Changed

Filename Overview
app/src/main/java/io/nekohasekai/sagernet/utils/DefaultNetworkListener.kt Routes callback lifecycle through the new helper and adds fallback start delivery, but the persistent cleanup-failure path can still skip ongoing callback updates.
app/src/main/java/io/nekohasekai/sagernet/utils/NetworkCallbackRegistration.kt Adds state tracking for callback register and unregister success or failure.
app/src/test/java/io/nekohasekai/sagernet/utils/NetworkCallbackRegistrationTest.kt Adds tests for callback registration, unregister retry, duplicate avoidance, and already-unregistered handling.

Reviews (5): Last reviewed commit: "fix(network): preserve listener after fa..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds a stateful NetworkCallbackRegistration helper, updates DefaultNetworkListener to use result-based callback lifecycle handling and fallback delivery, and adds tests covering success, failure, recovery, and repeated unregistration.

Changes

Network callback lifecycle

Layer / File(s) Summary
Registration state helper
app/src/main/java/io/nekohasekai/sagernet/utils/NetworkCallbackRegistration.kt
Tracks registration and fallback state while converting registration or unregistration exceptions into Result values.
Listener integration and validation
app/src/main/java/io/nekohasekai/sagernet/utils/DefaultNetworkListener.kt, app/src/test/java/io/nekohasekai/sagernet/utils/NetworkCallbackRegistrationTest.kt
Routes callback operations through the helper, delivers the active network during fallback startup, logs failures, and tests lifecycle behavior across success, failure, recovery, and repeated unregistration.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Poem

I’m a rabbit with callbacks to bind,
Registration states neatly aligned.
Failures are caught,
Fallbacks are taught,
And tests leave no bug behind.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: preserving the network listener through callback fallback.
Description check ✅ Passed The description is directly related to the PR and accurately covers the callback fallback and state-tracking changes.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

Comment thread app/src/main/java/io/nekohasekai/sagernet/utils/NetworkCallbackRegistration.kt Outdated
@hawkff
hawkff force-pushed the fix/007-network-listener-fallback branch from ef30d16 to dd6323a Compare July 12, 2026 22:36
Comment thread app/src/main/java/io/nekohasekai/sagernet/utils/NetworkCallbackRegistration.kt Outdated
@hawkff
hawkff force-pushed the fix/007-network-listener-fallback branch from dd6323a to c391f99 Compare July 12, 2026 22:56
@hawkff
hawkff force-pushed the fix/007-network-listener-fallback branch from c391f99 to d1b50a1 Compare July 12, 2026 23:14
@hawkff
hawkff force-pushed the fix/007-network-listener-fallback branch from d1b50a1 to 5ff2347 Compare July 12, 2026 23:27
Comment on lines +166 to +167
fallback = true
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Fallback Still Stalls When unregister cleanup keeps failing, this branch returns before installing a new Android network callback. The next Start only receives the current activeNetwork, so later Wi-Fi/mobile switches or network loss are not delivered through onAvailable or onLost. After a service restart in this state, underlyingNetwork can stay stale for the rest of the process unless the old callback is still active.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No change. After repeated platform cleanup failures, callback ownership is unknown. Registering again could create duplicate callbacks and conflicting stale events. The listener retries cleanup on each restart, delivers the current active network while uncertain, and keeps the actor alive; conservative fallback is the safe residual behavior.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point — when unregister fails, the old callback's ownership is genuinely ambiguous, and a blind re-register in that state could produce duplicates or conflicting onAvailable/onLost events that are harder to reason about than a known-stale snapshot. The retry-on-restart + current-network delivery is a coherent conservative contract.

Withdrawing the concern. The fallback behavior is intentional and the reasoning is sound.

@hawkff

hawkff commented Jul 12, 2026

Copy link
Copy Markdown
Owner Author

Latest commit passed Namespace CI run 29213429522.

@hawkff
hawkff merged commit 956549d into main Jul 12, 2026
9 checks passed
@hawkff
hawkff deleted the fix/007-network-listener-fallback branch July 13, 2026 01:29
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.

1 participant