Skip to content

fix(gool): stop polling the task that ended the tunnel - #91

Merged
CluvexStudio merged 1 commit into
CluvexStudio:mainfrom
amir-reza-bijandi:fix/gool-join-handle-panic
Aug 29, 2026
Merged

fix(gool): stop polling the task that ended the tunnel#91
CluvexStudio merged 1 commit into
CluvexStudio:mainfrom
amir-reza-bijandi:fix/gool-join-handle-panic

Conversation

@amir-reza-bijandi

@amir-reza-bijandi amir-reza-bijandi commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Closes #87 — the panic log, the environment it reproduces on, and the same root-cause analysis are in that issue; the short version is below.

The bug

Selecting Gool as the connection method panicked the app, and reconnecting afterwards would not come back up.

run_warp_in_warp runs three tasks — the outer WireGuard tunnel, the inner one, and the SOCKS5 server — and waits on them with tokio::select!. select! drives one of those JoinHandles to completion, but the shutdown path right after it aborted and awaited all three:

outer_exit.abort();
inner_exit.abort();
socks_task.abort();

let _ = outer_exit.await;
let _ = inner_exit.await;
let _ = socks_task.await;

Awaiting a JoinHandle that has already yielded Ready makes tokio panic with JoinHandle polled after completion, so whichever of the three finished first took the app down with it, and the aborted-mid-teardown state was why a reconnect could not recover.

The fix

Record which handle won the select!, then abort and await only the other two. The winning handle is already resolved, so it is simply left alone.

Testing

  • cargo check is clean.
  • Ran the app with Gool selected: it connects, and disconnect/reconnect cycles work instead of panicking.

A note on this PR

Full disclosure: I put this together with Claude Code, and I don't know Rust myself, so I can't vouch for the code the way a Rust developer could — please review it as such.

What I can say is that I've been patching every version of Aether with this fix and running it, and Gool has been solid since: no panic, and reconnecting works. I hope you'll consider taking it upstream so I can stop re-applying it by hand.

The select! in run_warp_in_warp already drives one of the three join
handles to completion, and the shutdown path then aborted and awaited
all three. Awaiting a JoinHandle that has already yielded Ready makes
tokio panic with "JoinHandle polled after completion", so picking Gool
brought the app down as soon as either tunnel or the socks server
stopped, and the panic left the runtime in a state where reconnecting
could not come back up.

Remember which handle won the select! and only abort and await the
other two.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@CluvexStudio

CluvexStudio commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Thanks for the fix! I’ll review the PR and merge it if everything looks good. :))

@CluvexStudio
CluvexStudio merged commit 034ad9d into CluvexStudio:main Aug 29, 2026
@TheLordOfTheKings

TheLordOfTheKings commented Aug 30, 2026

Copy link
Copy Markdown

There is still no auto-reconnect trigger after inner/outer tunnel failure? even after a while in a successful/established connection, if each of tunnels fail there is still no auto-reconnect.

image

@amir-reza-bijandi

Copy link
Copy Markdown
Contributor Author

Good catch — you're right that it doesn't come back on its own. It's a second bug sitting behind the one this PR fixed, and it's older than this PR.

Your log actually shows the merged fix doing its job: the tunnel went stale at 16:17:53, gool tunnel ended: ...; reconnecting, then it retried and reported failed 2 times in a row. Before the fix, the first of those drops would have panicked with JoinHandle polled after completion and taken the process down, so the loop never got that far.

What stops it is the next line: blacklisting and rescanning, and then the scan-mode menu. run_gool asks for the scan mode and the IP version from inside its reconnect loop, so a rescan waits for a keystroke — and hours into a session there is nobody at the terminal to press one. run_masque and run_wireguard ask once before their loops and reuse the answer; gool is the odd one out. It has been that way since the loop was written, so it is not something this PR introduced — the panic was just hiding it.

Until it's fixed there's a workaround that makes reconnect fully unattended: pass --scan balanced -4 (or set AETHER_SCAN / AETHER_IP). With those set it never has to ask.

I've opened #98 with the fix — hoisting both prompts above the loop so gool matches the other two transports.

One thing from your log that isn't part of this: both tunnels reported no valid data from peer ... in 6411.045s at the same instant, and that check is meant to fire after 10s. That looks like the machine was asleep for ~1h47m and the clock jumped on resume, rather than a slow detector.

Same disclaimer as the PR: written with Claude Code, and I don't know Rust myself.

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.

Gool (WARP-in-WARP) crashes with "JoinHandle polled after completion" panic on reconnect

3 participants