Skip to content

fix(log): create log file when arming SIGSEGV handler fd - #648

Merged
dmtrKovalenko merged 1 commit into
mainfrom
triage-bot/issue-641
Jul 2, 2026
Merged

dmtrKovalenko merged 1 commit into
mainfrom
triage-bot/issue-641

Conversation

@gustav-fff

Copy link
Copy Markdown
Collaborator

Refs #641

Root cause

sigsegv::set_log_fd() (crates/fff-core/src/log.rs:38) opens the log
file with .append(true).open(path) — no create(true). It runs at
log.rs:225, before init_tracing opens/creates the writer file
at log.rs:237. On the first-ever nvim session for a given user the
log file does not yet exist, so the open fails silently, LOG_FD stays
-1, and when a segfault later fires the banner is written to fd 2
only via:

libc::write(2, BANNER.as_ptr().cast(), BANNER.len());
let log_fd = LOG_FD.load(Ordering::Relaxed);
if log_fd >= 0 {                     // never true — LOG_FD is -1
    libc::write(log_fd, BANNER.as_ptr().cast(), BANNER.len());
}

Neovim discards stderr on exit-to-shell, so the user sees the terminal
banner but the log file never contains === CRASH SIGSEGV (fff) ===.
This is exactly the "the banner is not in my log" complaint in #641.

Once the writer file exists (post-first-session), set_log_fd succeeds
and the banner does land in the log — which explains why the same crash
can be logged for some users but never for others.

Fix

Add .create(true) to the set_log_fd open. Now the fd is armed even
on first launch, and the SIGSEGV path writes the banner into the file
alongside stderr.

Steps to reproduce

Pre-fix, on a machine with no existing fff log dir:

# Ensure log dir is clean for the target session
rm -f "$(nvim --headless -c 'lua io.write(vim.fn.stdpath("log"))' -c 'qa!' 2>&1)"/fff*.log

# Force a segfault after init — easiest via a test binary that calls
# `fff_search::log::init_tracing` and then dereferences a null pointer.
# The `=== CRASH SIGSEGV (fff) ===` banner appears on stderr but the
# freshly-created session log file contains no crash section.
grep 'CRASH SIGSEGV' "$XDG_STATE_HOME/nvim"/fff*.log   # → no matches

Post-fix: same reproduction, grep 'CRASH SIGSEGV' finds the banner in
the log file on the very first session, matching the guidance in the
banner itself ("Please file the bug ... with this banner attached").

How verified

  • cargo check -p fff-search — clean.
  • Verified independently with a standalone rust snippet that
    OpenOptions::new().append(true).open(nonexistent) returns Err
    while .create(true).append(true).open(nonexistent) succeeds — this
    is the exact silent-fail that was hiding the banner.

Notes

  • Does not address the underlying segfault the reporter is hitting —
    that still requires an attachable crash section from the log or a
    gdb backtrace, per [Bug]: neovim plugin crashes neovim when opening a file #641. This PR makes the crash section actually
    reachable so future reports carry the frames.

Automated triage via Gustav. Honk-Honk 🪿

sigsegv::set_log_fd() runs before init_tracing opens/creates the
writer file. Its previous OpenOptions used append(true) with no
create(true), so on the first-ever session the file did not yet
exist, the open failed silently, and LOG_FD stayed -1. When a
segfault later fired the banner was written to fd 2 only; nvim
discards stderr, and nothing ever hit the log — leaving users
with only the terminal banner and no attachable crash section.

Refs #641.
@dmtrKovalenko
dmtrKovalenko merged commit 4ac67d0 into main Jul 2, 2026
51 checks passed
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.

2 participants