Repository navigation
Kitty graphics causing crashes macOS + Linux #5453
|
After displaying an image using the Kitty graphics protocol, Ghostty will crash when performing a screen clear. While it doesn't happen all the time, I believe the primary cause is when a image displayed is larger than the terminal's viewport, or alternately when it's just a large image file. This behavior can be reproduced by using the $ git clone https://github.com/kenshaw/iv.git && cd iv
$ go build
$ iv ./testdata/vips/*
$ clearNote that a crash report will not be generated when Alternately, a crash will also occur when calling $ tput resetThis is the captured console output of $ ghostty
info: ghostty version=1.1.0-arch
info: ghostty build optimize=ReleaseFast
info: runtime=apprt.Runtime.gtk
info: font_backend=font.main.Backend.fontconfig_freetype
info: dependency harfbuzz=10.2.0
info: dependency fontconfig=21600
info: renderer=renderer.OpenGL
info: libxev backend=main.Backend.io_uring
info(os): setlocale from env result=en_US.UTF-8
info(gtk): GTK version build=4.16.12 runtime=4.16.12
info: reading configuration file path=/home/ken/.config/ghostty/config
info(config): default shell source=env value=/usr/bin/bash
warning(gtk): setting GDK_DEBUG=gl-no-fractional
warning(gtk): setting GDK_DISABLE=gles-api,vulkan
warning(gtk): setting GSK_RENDERER=opengl
info(gtk): libadwaita version build=1.6.3 runtime=1.6.3
info(grid): loaded OpenGL 4.6
info(font_shared_grid_set): font regular: Inconsolata LGC Nerd Font Mono
info(font_shared_grid_set): font bold: Inconsolata LGC Nerd Font Mono Bold
info(font_shared_grid_set): font italic: Inconsolata LGC Nerd Font Mono Italic
info(font_shared_grid_set): font bold_italic: Inconsolata LGC Nerd Font Mono Bold Italic
info(io_exec): found Ghostty resources dir: /usr/share/ghostty
info(io_exec): shell integration automatically injected shell=termio.shell_integration.Shell.bash
warning(gtk): unimplemented action=apprt.action.Action.Key.cell_size
info(io_exec): started subcommand path=/bin/sh pid=3666646
info(io_exec): subcommand cgroup=-
warning(gtk): unimplemented action=apprt.action.Action.Key.key_sequence
warning(gtk): unimplemented action=apprt.action.Action.Key.cell_size
warning(gtk): unimplemented action=apprt.action.Action.Key.key_sequence
warning(gtk): unimplemented action=apprt.action.Action.Key.cell_size
info(grid): reallocating GPU buffer old=0 new=8
info(grid): reallocating GPU buffer old=8 new=65
warning(stream): unimplemented OSC callback: terminal.osc.Command{ .end_of_command = terminal.osc.Command.Command__struct_97274{ .exit_code = 0 } }
warning(stream): unimplemented OSC command: end_of_command
info(grid): reallocating GPU buffer old=65 new=255
info(kitty_gfx): evicting images to make space for 74521088 bytes
info(kitty_gfx): evicting image id=2147483647 bytes=45120000
info(kitty_gfx): evicting image id=2147483648 bytes=144769024
warning(stream): unimplemented OSC callback: terminal.osc.Command{ .end_of_command = terminal.osc.Command.Command__struct_97274{ .exit_code = 0 } }
warning(stream): unimplemented OSC command: end_of_command
Segmentation fault (core dumped)The terminal output is similar on macOS. I've written a quick Go script that will always crash Ghostty, when run on a 4k display: package main
import (
"fmt"
"image"
"image/color"
"log"
"os"
"github.com/kenshaw/rasterm"
)
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
func run() error {
const width, height = 8000, 8000
img := image.NewRGBA(image.Rect(0, 0, width, height))
for x := range width {
for y := range height {
img.SetRGBA(x, y, color.RGBA{
R: 128,
G: 128,
B: 128,
A: 128,
})
}
}
if err := rasterm.Encode(os.Stdout, img); err != nil {
return err
}
_, err := fmt.Fprintf(os.Stdout, "\x1bc")
return err
}Note that I have used the // Encode satisfies the [Encoder] interface.
func (r KittyEncoder) Encode(w io.Writer, img image.Image) error {
buf := new(bytes.Buffer)
enc := base64.NewEncoder(base64.StdEncoding, buf)
if err := png.Encode(enc, img); err != nil {
return err
}
if err := enc.Close(); err != nil {
return err
}
if err := chunkEncode(w, buf.Bytes(), 4096); err != nil {
return err
}
if r.NoNewline {
return nil
}
_, err := fmt.Fprintln(w)
return err
}
// chunkEncode writes buf to w in chunks.
func chunkEncode(w io.Writer, buf []byte, size int) error {
if _, err := fmt.Fprintf(w, "\x1b_Ga=T,f=100,m=1;\x1b\\"); err != nil {
return err
}
n := len(buf)
for i, j, m := 0, min(size, n), 0; i < n; i, j = j, min(j+size, n) {
if m = 0; j < n {
m = 1
}
if _, err := fmt.Fprintf(w, "\x1b_Gm=%d;%s\x1b\\", m, buf[i:j]); err != nil {
return err
}
}
return nil
}This is likely related to the following open discussions, or quite possibly the same bug: |
Replies: 2 comments
|
I'm attaching the captured output of the Go code above: Simply $ cat bad.txt |
Apologies, this #3576 seems to be the same issue.