microsoft / microsoft/vscode-remote-release

[Remote Tunnels] Tunnel process becomes zombie (silent, no relay reconnect) after all clients disconnect and Extension Host shuts down

Open
#11,550 3 comments 0 reactions 1 assignee View on GitHub

@connor4312 is already working on this.

Since Mar 24, 2026.

bug
Dominant language
Dockerfile
Stars
4.2k
Forks
469
Avg merge
1d 1h
Merged PRs (30d)
1

Description

Summary

When all clients disconnect from a code tunnel (systemd user service), the reconnection grace period expires (default 3h), the Extension Host shuts down, and the relay WebSocket closes — the tunnel process does not attempt to re-establish the relay connection. It stays alive silently (no log output), and the tunnel appears offline on vscode.dev indefinitely. The only recovery is a full tunnel service uninstall + tunnel service install.

Environment

  • VS Code CLI version: 1.112.0 (commit 07ff9d6178ede9a1bd12ad3399074d726ebe6e43)
  • OS: Ubuntu 24.04 LTS (Linux 6.17.0, x86_64)
  • Deployment: code tunnel service install → systemd user service with Restart=always
  • Tunnel name: managed via jpe1.rel.tunnels.api.visualstudio.com

Steps to Reproduce

  1. Run code tunnel service install and connect from vscode.dev.
  2. Close all browser/client connections to the tunnel.
  3. Wait for the ManagementConnection reconnection grace period to expire (3 hours).
  4. Observe the Extension Host shutdown: Last EH closed, shutting down.
  5. Check vscode.dev — tunnel shows offline.
  6. Check systemctl --user status code-tunnel — process is still running (Active: running).
  7. Check journalctl --user -u code-tunnelcomplete silence from this point on; no reconnection attempts, no errors.

Expected Behavior

After the relay WebSocket closes (due to all clients disconnecting / EH shutdown), the tunnel process should re-register with the relay and restore the "online" state, so new clients can connect without manual intervention.

Actual Behavior

The process enters a zombie state: alive (no exit, so Restart=always never triggers) but permanently disconnected from the relay. The tunnel remains offline on vscode.dev until the service is manually uninstalled and reinstalled.

Relevant Log Sequence

# Client disconnects, grace period starts
[07:48:11] [<unknown>][59b930de][ManagementConnection] The client has disconnected, will wait for reconnection 3h before disposing...

# 3h later — grace period expires
[10:48:19] [<unknown>][59b930de][ManagementConnection] The reconnection grace time of 3h has expired, so the connection will be disposed.

# Extension Host shuts down
[10:52:51] Last EH closed, shutting down

# ← Complete silence from this point. No relay reconnect attempt. Ever.

Note: immediately before the grace period started, a transient DNS failure was observed during a relay reconnect cycle:

[07:47:46] warn failed to check GitHub token: error sending request for url (https://api.github.com/user): error trying to connect: dns error: failed to lookup address information: Try again

This may have contributed to the relay WebSocket not being re-established properly, but the core issue is that the process never retries.

Workaround

A watchdog script (run via systemd timer every 5 minutes) that detects log silence > 10 minutes and calls systemctl --user restart code-tunnel. This works because --verbose mode produces continuous output (liveness pongs, etc.) when the relay is genuinely connected.

Additional Context

  • The process is running as a systemd user service (loginctl enable-linger is set).
  • Two processes are spawned: a singleton server (long-lived) and a client wrapper that reconnects to it on respawn. After the EH shutdown, neither process attempts relay re-registration.
  • Restart=always / RestartSec=10 in the service unit does not help because the process never exits.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.