Skip to content

feat(network/onion): detect liveness via TcpStream close - #5168

Merged
chenyukang merged 1 commit into
nervosnetwork:developfrom
jetjinser:5161
Jul 24, 2026
Merged

feat(network/onion): detect liveness via TcpStream close#5168
chenyukang merged 1 commit into
nervosnetwork:developfrom
jetjinser:5161

Conversation

@jetjinser

@jetjinser jetjinser commented Apr 11, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #5161
Follow-up to #5271.

Problem Summary:

The onion service currently polls the Tor daemon every 3 seconds via get_uptime() to detect connection loss. This adds unnecessary latency (up to 3s for failure detection) and constant I/O overhead. A passive, event-driven approach would react instantly and reduce resource usage.

What is changed and how it works?

What's Changed:

  • An oneshot channel notifies TorController when either copy direction terminates (EOF or error).
  • Replaced the 3-second ticker loop in OnionService with a branch awaiting wait_for_disconnect().

Related changes

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No code

Manual test steps:

  1. ckb run with config listen_on_onion = true.
  2. Observe the onion service starts successfully.
  3. Kill/exit the Tor process.
  4. Verify the node logs "Tor control connection lost" within milliseconds, not after a multi-second delay.
  5. Restart the Tor daemon and verify the onion service can be re-established.

Side effects

  • Performance regression
  • Breaking backward compatibility

@jetjinser
jetjinser requested a review from a team as a code owner April 11, 2026 07:10
@jetjinser
jetjinser requested review from doitian and removed request for a team April 11, 2026 07:10
@jetjinser
jetjinser force-pushed the 5161 branch 2 times, most recently from c4b6a66 to cdc4bce Compare April 12, 2026 14:52
Comment thread util/onion/src/tor_controller.rs Outdated
@eval-exec

eval-exec commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

I'm thinking we might not need to depend on torut after all. 🤔

@jetjinser

Copy link
Copy Markdown
Contributor Author

I'm thinking we might not need to depend on torut after all. 🤔

Sounds reasonable, I'll try to do so

@jetjinser

Copy link
Copy Markdown
Contributor Author

@eval-exec Hi, I made a PR for this attempt: #5271

@jetjinser

Copy link
Copy Markdown
Contributor Author

Since #5271 has been merged, I pushed a simpler implementation and updated the PR description.
Please take a look @eval-exec :)

@eval-exec
eval-exec requested review from Copilot and removed request for doitian July 24, 2026 03:19

Copilot AI 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.

Pull request overview

This PR changes Tor liveness detection in the onion service from periodic GETINFO uptime polling to an event-driven approach by waiting for the Tor control TcpStream to close, reducing control-port traffic and failure-detection latency.

Changes:

  • Added a oneshot-based disconnect notification from the Tor control connection reader task.
  • Exposed wait_for_disconnect() on TorController/TorConnection to await connection loss.
  • Replaced the 3-second polling loop in OnionService with a tokio::select! awaiting disconnect or shutdown.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
util/onion/src/tor_controller.rs Adds a wait_for_disconnect() API forwarding to the underlying connection (docs currently mismatched with return type).
util/onion/src/tor_connection.rs Introduces oneshot disconnect signaling from the reader task and a wait_for_disconnect() awaitable (currently risks dropping stream halves too early).
util/onion/src/onion_service.rs Switches liveness monitoring from periodic uptime polling to waiting on the disconnect notification.

Comment on lines +252 to 255
/// Wait for the underlying TCP connection to close.
pub async fn wait_for_disconnect(self) -> bool {
self.disconnect_rx.await.is_ok()
}
Comment on lines +107 to +112
/// Returns `Some(())` when the connection is lost, or `None` if the internal
/// notification channel was closed unexpectedly (which should not occur during
/// normal operation).
pub async fn wait_for_disconnect(self) -> bool {
self.inner.wait_for_disconnect().await
}
Comment on lines +252 to 255
/// Wait for the underlying TCP connection to close.
pub async fn wait_for_disconnect(self) -> bool {
self.disconnect_rx.await.is_ok()
}
@chenyukang
chenyukang merged commit 946c655 into nervosnetwork:develop Jul 24, 2026
32 of 42 checks passed
@github-project-automation github-project-automation Bot moved this from 🆕 New to ✅ Done in Kanban Jul 24, 2026
@nervos-bot nervos-bot Bot mentioned this pull request Jul 24, 2026
@jetjinser
jetjinser deleted the 5161 branch July 24, 2026 04:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

network/onion: detect Tor liveness via socket close instead of polling

4 participants