Skip to content

Commit 3fa8f2d

Browse files
committed
Tear down SSH tunnel on abnormal client disconnect
`nrepl--ssh-tunnel-connect' spawns a separate `ssh' subprocess for port forwarding and stashes it on the client buffer's `nrepl-tunnel-buffer'. The orderly teardown path -- `cider-quit' -> `cider--close-connection' -- already kills the tunnel buffer. But the `nrepl-client-sentinel' path, which fires on abnormal client- process death (server crash, network drop, kill -9), only ran the disconnect hooks and the maybe-kill-server-buffer cleanup. Neither touches the tunnel, so the `ssh' subprocess kept running until Emacs itself exited. Add the tunnel cleanup to the sentinel, symmetric with the existing `nrepl--maybe-kill-server-buffer' call. Same layering: the transport sentinel owns transport-infrastructure cleanup.
1 parent b95dcc9 commit 3fa8f2d

2 files changed

Lines changed: 12 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
- `nrepl--ssh-tunnel-connect` no longer routes its `ssh` invocation through a shell. The tunnel command is now spawned via `start-process` with an explicit arg list, eliminating shell-quoting hazards in user/host components.
2424
- Plug five request-id leaks in raw nREPL response handlers (`cider/test-stacktrace`, `cider/test-var-query`, `cider/analyze-last-stacktrace`, `cider/ns-reload`, `cider/get-state`). They never called `nrepl--mark-id-completed`, so their ids accumulated in the connection's `nrepl-pending-requests` for the lifetime of the session.
2525
- A response-handler error or an unrecognized response id no longer aborts the nREPL response queue. `nrepl-client-filter` wraps the dispatch call in `with-demoted-errors`, and the no-callback case in `nrepl--dispatch-response` is now a `message` instead of a hard error -- so a single misbehaving callback can no longer drop later responses on the floor.
26+
- `nrepl-client-sentinel` now tears down the SSH tunnel buffer/process when the client connection closes. Previously only the orderly `cider-quit` path killed the tunnel, so an abnormal disconnect (server crash, network drop) left the `ssh` subprocess as a zombie until Emacs exited.
2627

2728
### Changes
2829

lisp/nrepl-client.el

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,17 @@ and kill the process buffer."
343343
(current-time-string)))
344344
'face 'error))
345345
(run-hooks 'nrepl-disconnected-hook)
346+
;; Tear down the SSH tunnel, if any, so its `ssh' subprocess
347+
;; doesn't outlive the connection. The orderly path through
348+
;; `cider--close-connection' already does this; we duplicate it
349+
;; here so abnormal disconnects (server crash, network drop,
350+
;; client process killed) don't leak the tunnel.
351+
(when (buffer-live-p nrepl-tunnel-buffer)
352+
(when-let* ((tunnel-proc (get-buffer-process nrepl-tunnel-buffer)))
353+
(when (process-live-p tunnel-proc)
354+
(delete-process tunnel-proc)))
355+
(kill-buffer nrepl-tunnel-buffer))
356+
(setq nrepl-tunnel-buffer nil)
346357
(let ((server-buffer nrepl-server-buffer))
347358
(when (and (buffer-live-p server-buffer)
348359
(not (process-get process :keep-server)))

0 commit comments

Comments
 (0)