fix: main loop never closed, disconnect-daemon ran every iteration

The main loop's closing paren was missing — (sleep 0.1)) only closed
sleep and the minibuffer let, but NOT the loop itself. The next form
(progn (disconnect-daemon)) was INSIDE the loop body, called on every
iteration. On first call it added '* Disconnected *' and cleared the
daemon stream, making the TUI permanently disconnected.

Fix: add ) to close the loop. Also:
- Connect-daemon runs synchronously BEFORE with-terminal (3 ports, 6s
  max). If daemon is already running, the TUI starts connected.
- If sync connect fails, background thread retries every 5 seconds.
- start-daemon in background (no blocking wait for daemon startup),
  so TUI appears immediately.
This commit is contained in:
2026-05-15 12:08:40 -04:00
parent bd1e8a92be
commit df33e8d6db
2 changed files with 27 additions and 19 deletions

View File

@@ -757,23 +757,18 @@ supplied (e.g. \"/\"), pre-fill the select filter with it."
** Connection
#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-main.lisp
(defun connect-daemon (&optional (host "127.0.0.1") (start-port 9105) (end-port 9115))
"Connect to daemon, trying ports START-PORT to END-PORT."
(add-msg :system (format nil "* Connecting to daemon... *"))
"Try to connect to daemon once across START-PORT to END-PORT.
Returns T on success, nil on failure. Does NOT wait or retry."
(loop for port from start-port to end-port
do (handler-case
(let ((s (usocket:socket-connect host port :timeout 2)))
(setf (st :stream) (usocket:socket-stream s)
(st :connected) t)
(add-msg :system (format nil "* Connected to daemon on port ~d *" port))
(bt:make-thread (lambda () (reader-loop (st :stream)))
:name "tui-reader")
(return-from connect-daemon t))
(usocket:connection-refused-error ()
(when (= port end-port)
(add-msg :system (format nil "* No daemon on ports ~d-~d *" start-port end-port))))
(error (c)
(when (= port end-port)
(add-msg :system (format nil "* No daemon on ports ~d-~d (error: ~a) *" start-port end-port c))))))
(bt:make-thread (lambda () (reader-loop (st :stream)))
:name "tui-reader")
(return-from connect-daemon t))
(usocket:connection-refused-error () nil)
(error (c) nil)))
nil)
(defun disconnect-daemon ()
@@ -884,7 +879,10 @@ supplied (e.g. \"/\"), pre-fill the select filter with it."
(parse-integer (uiop:getenv "TUI_SWANK_PORT")))
4006)))
(setf (st :dirty) (list t t t))
(connect-daemon)
;; Quick sync connect attempt (just 3 ports, 6s max)
(let ((connected (connect-daemon "127.0.0.1" 9105 9107)))
(unless connected
(add-msg :system "* Daemon not found — will retry in background... *")))
(when (> swank-port 0)
(handler-case
(progn
@@ -902,10 +900,19 @@ supplied (e.g. \"/\"), pre-fill the select filter with it."
(add-msg :system (format nil "* ~a backend ~dx~d *"
(if (typep be 'cl-tty.backend:modern-backend) "modern" "simple")
w h))
;; Initial dirty all to trigger first redraw in loop
;; Initial dirty all to trigger first redraw in loop
(setq w (or (and (numberp w) (> w 0) w) 80)
h (or (and (numberp h) (> h 0) h) 24))
(loop while (st :running) do
;; Retry daemon connection in background if sync attempt failed
(unless (st :connected)
(add-msg :system "* Connecting to daemon... *")
(bt:make-thread
(lambda ()
(loop while (and (st :running) (not (st :connected)))
do (connect-daemon)
(unless (st :connected) (sleep 5))))
:name "daemon-auto-connect"))
(loop while (st :running) do
(dolist (ev (drain-queue))
(cond
((eq (getf ev :type) :daemon)
@@ -1077,8 +1084,8 @@ supplied (e.g. \"/\"), pre-fill the select filter with it."
(format nil "> ~a" (or filter ""))
(theme-color :input-prompt) nil))
(cl-tty.backend:end-sync be))
(sleep 0.1))
(progn (disconnect-daemon))))))
(sleep 0.1)))
(progn (disconnect-daemon)))))
#+END_SRC
* Test Suite