Skip to content

fix: process recovery#4

Merged
Yukaii merged 3 commits into
mainfrom
bugfix/process-recovery
Feb 1, 2026
Merged

fix: process recovery#4
Yukaii merged 3 commits into
mainfrom
bugfix/process-recovery

Conversation

@Yukaii

@Yukaii Yukaii commented Feb 1, 2026

Copy link
Copy Markdown
Owner
  • fix: try recover the process
  • fix: force an update
  • fix(fifo): reduce idle cpu polling

fixes #3

Copilot AI review requested due to automatic review settings February 1, 2026 00:21
@github-actions

github-actions Bot commented Feb 1, 2026

Copy link
Copy Markdown

Performance Test Results

Metric Value Threshold
Small file (100 lines) 134.58ms 300ms
Medium file (1000 lines) 178.69ms 1000ms
Large file (10000 lines) 661.61ms 5000ms
Memory delta 0.00MB 150MB

Status: ✅ Performance within acceptable thresholds


Tested on: ubuntu-latest, x86_64

@Yukaii Yukaii merged commit 7893278 into main Feb 1, 2026
12 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes Kakoune ↔ server FIFO update flow by improving server/process recovery and reducing idle CPU usage during FIFO reads.

Changes:

  • Reduce idle CPU polling in the Rust FIFO reader by using poll() before reads.
  • Add server/process recovery logic in giallo-buffer-update (restart on dead/wrong PID, missing server FIFO, PID change).
  • Trigger a buffer update once the per-buffer FIFO path becomes available after init.

Reviewed changes

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

File Description
src/fifo.rs Introduces poll()-based waiting to avoid tight loops when FIFO has no writers/data.
rc/giallo.kak Adds server restart/re-init checks and a new hook to force an update after FIFO init completes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/fifo.rs
Comment on lines +114 to +128
let poll_result = unsafe { libc::poll(&mut poll_fd, 1, 250) };
if poll_result < 0 {
log::warn!("reader: poll error: {}", io::Error::last_os_error());
thread::sleep(std::time::Duration::from_millis(50));
continue;
}
if poll_result == 0 {
continue;
}
if poll_fd.revents & libc::POLLIN == 0 {
if poll_fd.revents & libc::POLLHUP != 0 {
thread::sleep(std::time::Duration::from_millis(100));
}
continue;
}

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poll() errors are always logged and slept on. poll() can legitimately return -1 with EINTR, which will currently produce noisy warnings and unnecessary delays. Also, if revents contains POLLERR/POLLNVAL without POLLIN, the loop will silently continue, potentially spinning forever on a broken fd. Consider special-casing Interrupted to just retry, and treating POLLERR|POLLNVAL as an error that triggers a reopen/exit (with a clear log).

Copilot uses AI. Check for mistakes.
Comment thread rc/giallo.kak
# Write to FIFO in background to avoid blocking UI if server isn't ready yet.
# INIT format: INIT <session> <buffer> <token> <lang> <theme>
sh -c "printf 'INIT %s %s %s %s %s\n' '$session' '$buffer' '$token' '$lang' '$theme' > '$fifo'" >/dev/null 2>&1 &
printf 'hook -once buffer BufSetOption giallo_buf_fifo_path=.* %%{ giallo-buffer-update }\n'

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

giallo-enable already registers a hook -once buffer BufSetOption giallo_buf_fifo_path=.* handler (lines 129-135) and giallo-init-buffer now adds another one. If giallo-init-buffer is called repeatedly before giallo_buf_fifo_path is set (e.g. during reconnect), this can enqueue multiple -once hooks and cause duplicate giallo-buffer-update runs once the option is set. Consider de-duplicating by using a hook -group and removing/replacing it, or rely on a single existing hook for this event.

Suggested change
printf 'hook -once buffer BufSetOption giallo_buf_fifo_path=.* %%{ giallo-buffer-update }\n'

Copilot uses AI. Check for mistakes.
Comment thread rc/giallo.kak
Comment on lines +210 to +240
if [ -n "$server_pid" ]; then
if ! kill -0 "$server_pid" >/dev/null 2>&1; then
printf 'giallo-stop-server\n'
printf 'giallo-start-server\n'
printf 'giallo-init-buffer\n'
exit 0
fi
server_comm=$(ps -p "$server_pid" -o comm= 2>/dev/null || true)
case "$server_comm" in
(*giallo-kak*) ;;
(*)
printf 'giallo-stop-server\n'
printf 'giallo-start-server\n'
printf 'giallo-init-buffer\n'
exit 0
;;
esac
fi

if [ -n "$server_req" ] && [ ! -p "$server_req" ]; then
printf 'giallo-stop-server\n'
printf 'giallo-start-server\n'
printf 'giallo-init-buffer\n'
exit 0
fi

# Update the last update timestamp

server_pid_seen="$kak_opt_giallo_server_pid_seen"
if [ -n "$server_pid" ] && [ "$server_pid" != "$server_pid_seen" ]; then
printf 'set-option buffer giallo_server_pid_seen %s\n' "$server_pid"
printf 'giallo-init-buffer\n'
exit 0

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new server recovery paths (PID liveness check + ps validation + giallo_server_pid_seen-based re-init) introduce important behavior that isn't exercised anywhere in the existing test suite. Adding/strengthening an E2E test that kills the server and verifies giallo-buffer-update automatically restarts and re-initializes the buffer would help prevent regressions.

Copilot uses AI. Check for mistakes.
Comment thread rc/giallo.kak
@@ -165,6 +167,7 @@ define-command -docstring "Initialize per-buffer FIFO for giallo" giallo-init-bu
# Write to FIFO in background to avoid blocking UI if server isn't ready yet.
# INIT format: INIT <session> <buffer> <token> <lang> <theme>
sh -c "printf 'INIT %s %s %s %s %s\n' '$session' '$buffer' '$token' '$lang' '$theme' > '$fifo'" >/dev/null 2>&1 &

Copilot AI Feb 1, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sh -c invocation in giallo-init-buffer builds a shell command string that embeds unescaped values like session, buffer, and token inside single quotes, which can lead to shell command injection if any of these contain a single quote or shell metacharacters (e.g., from a crafted buffer name or session name). An attacker who can influence kak_bufname (for example via a file with a specially crafted name) could break out of the intended quoting and inject arbitrary commands executed with the user's privileges when giallo-init-buffer runs. To fix this, avoid constructing a shell command string with these values (e.g., write directly to the FIFO in the current shell or pass values as positional parameters) or ensure that all embedded values are robustly escaped for the shell, including single quotes.

Suggested change
sh -c "printf 'INIT %s %s %s %s %s\n' '$session' '$buffer' '$token' '$lang' '$theme' > '$fifo'" >/dev/null 2>&1 &
( printf 'INIT %s %s %s %s %s\n' "$session" "$buffer" "$token" "$lang" "$theme" >"$fifo" ) >/dev/null 2>&1 &

Copilot uses AI. Check for mistakes.
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.

If the process gets killed when Kakoune is open, I get stuck "waiting while writing buffer"

2 participants