Repository navigation
fix: say why the window died, in the log and the dialog - #589
Merged
Merged
Conversation
The window's stderr went straight to lich's own, which a launcher start does not have, so a crash left only its signal in lich.log. launch now keeps a bounded tail of it and returns it on a failed exit: every log site records it, and the error dialog shows the FATAL lines.
omartelo
force-pushed
the
fix/window-stderr-in-log
branch
from
September 11, 2026 18:14
887b5eb to
9069001
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A lich 0.49.0 on Ubuntu opened no window, and
lich.logheld onlychromium shell err="signal: trace/breakpoint trap (core dumped)", then the same signal forfocus existing window. The reason was one Chromium FATAL on the window's stderr (the sandbox helper undercef/, fixed in #587), andlaunchhanded that stream straight to lich's own stderr, which a launcher start does not have.lich ragebundles the log, so it had nothing either.What changes
launchis where every window starts:Run,Focus, the macOS tab fallback insidestartupGrace, and Windows, which has no launch path of its own. So the fix is there and covers all four. The window's stderr now goes throughstderrTail, which passes every byte on to lich's stderr as before and keeps the end of it. A window that exits with an error comes back aschromium.ExitError, whose message is the exit followed by the tail, so each existing log site (chromium shell,focus existing window,bundled window died at startup, opening a tab instead) records it without a change at the call site. The dialog inmain.goshowschromium.Why(err): the exit and only the lines that say why.Measured against the installed 0.49.0
lich-shell, headless (--ozone-platform=headless), with--disable-namespace-sandboxto reach the same helper check:[..:FATAL:sandbox/linux/suid/client/setuid_sandbox_host.cc:166] The SUID sandbox helper binary was found, but is not configured correctly..., and exits on SIGTRAP with a core dumpBounds, and why FATAL lines win the space
Nothing is logged while the window runs:
lich.logrotates at 5 MiB and a healthy window is chatty. A failed exit logs its last 20 lines, each cut at 1 KiB. The first three FATAL orCheck failedlines are kept ahead of the tail once they scroll out of it, with...wherever lines around them were dropped. Chromium aborts on its first FATAL, so that line is the cause, and what follows it is consequence: subprocesses losing the browser and saying so, a crash dump, a GPU process restarting. In the crash measured here the FATAL line was the last one, so a plain tail would have caught it; the rule is for the crash whose cause is followed by more than 20 lines of fallout. First ones rather than last, because later FATALs are the cascade.The dialog gets those FATAL lines, at most three, or the last three lines when there are none. The whole tail in a dialog reads as a wall of warnings.
The pipe
os.Stderrwas a file the child inherited. A writer that is not a file makes exec copy through a pipe, andWaitthen returns only once every holder of the write end has closed it, the window's subprocesses included.WaitDelay(2 s) bounds that after the window exits, and theErrWaitDelayit reports, only ever after a clean exit, maps back to nil: the window closed as asked. The mirror swallows its own write errors for the same reason, since exec reports a copy error after a clean exit as the command failing, and the windowsgui build has no stderr to write to.Not covered
lich-shellprints itself. Written down indocs/ceilings.md, withlich -- --enable-logging=stderras the switch that asks for them.Test plan
gofmt -l .andgo vet ./...cleango test ./..., plus-raceoninternal/chromium(package coverage 92.7%,stderr.go100%)ExitErrorwrapping it;Whypicks FATAL lines over the noise, caps them at three and falls back to the last three lines;Focuson a stand-in window that writes a FATAL line and exits 5 returns that linetailLines,lineBytesandwhyLines, one either side, each fail the suitelich-shelland read the stderr and pipe timings abovelich.log