Make goroutines in choose_files panic safe

This commit is contained in:
Kovid Goyal 2025-10-09 08:11:47 +05:30
parent e61e95da3a
commit d598157590
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 40 additions and 14 deletions

View file

@ -269,6 +269,9 @@ func (self *GraphicsHandler) RenderImagePreview(h *Handler, p *ImagePreview, x,
img_metadata, cached_data := self.cached_resized_image(p.disk_cache.ResultsDir(), cache_key)
var img *images.ImageData
if len(cached_data) == 0 {
if err = p.ensure_source_image(); err != nil {
return
}
img = p.source_img
final_width, final_height := images.FitImage(img.Width, img.Height, px_width, px_height)
if final_width != img.Width || final_height != img.Height {

View file

@ -110,17 +110,26 @@ func (p *ImagePreview) ensure_source_image() (err error) {
return
}
func (p *ImagePreview) render_image(h *Handler, x, y, width, height int) {
defer func() {
if r := recover(); r != nil {
text, _ := utils.Format_stacktrace_on_panic(r)
h.err_chan <- fmt.Errorf("%s", text)
p.WakeupMainThread()
}
}()
offset := p.renderer.ShowMetadata(h, ShowData{
abspath: p.abspath, metadata: p.metadata, x: x, y: y, width: width, height: height, cached_data: p.cached_data,
img_metadata: p.img_metadata,
})
h.graphics_handler.RenderImagePreview(h, p, x, y+offset, width, height-offset)
}
func (p *ImagePreview) Render(h *Handler, x, y, width, height int) {
if p.render_channel == nil {
if p.render_err == nil {
offset := p.renderer.ShowMetadata(h, ShowData{
abspath: p.abspath, metadata: p.metadata, x: x, y: y, width: width, height: height, cached_data: p.cached_data,
img_metadata: p.img_metadata,
})
y += offset
height -= offset
h.graphics_handler.RenderImagePreview(h, p, x, y, width, height)
p.render_image(h, x, y, width, height)
} else {
p.render_err.Render(h, x, y, width, height)
}
@ -132,19 +141,28 @@ func (p *ImagePreview) Render(h *Handler, x, y, width, height int) {
p.cached_data = hd.cached_data
p.source_img = hd.img
p.img_metadata = hd.img_metadata
p.render_err = NewErrorPreview(fmt.Errorf("Failed to render the preview with error: %w", hd.err))
if hd.err != nil {
p.render_err = NewErrorPreview(fmt.Errorf("Failed to render the preview with error: %w", hd.err))
}
p.Render(h, x, y, width, height)
return
default:
}
if p.file_metadata_preview == nil {
p.file_metadata_preview = NewFileMetadataPreview(p.abspath, p.metadata)
m := p.file_metadata_preview.(*MessagePreview)
m.trailers = append(m.trailers, "", "Rendering image preview, please wait…")
}
p.file_metadata_preview.Render(h, x, y, width, height)
}
func (p *ImagePreview) start_rendering() {
defer func() {
if r := recover(); r != nil {
text, _ := utils.Format_stacktrace_on_panic(r)
p.render_channel <- render_data{err: fmt.Errorf("%s", text)}
}
close(p.render_channel)
p.WakeupMainThread()
}()
key, ans, err := p.disk_cache.GetPath(p.abspath)
@ -202,8 +220,7 @@ func (p ImagePreviewRenderer) ShowMetadata(h *Handler, s ShowData) int {
if s.img_metadata != nil {
text = fmt.Sprintf("%s: %dx%d %s", s.img_metadata.Format_uppercase, s.img_metadata.Width, s.img_metadata.Height, humanize.Bytes(uint64(s.metadata.Size())))
}
h.render_wrapped_text_in_region(text, s.x, s.y, s.width, s.height, false)
return 0
return h.render_wrapped_text_in_region(text, s.x, s.y, s.width, s.height, false)
}
func NewImagePreview(
@ -211,7 +228,7 @@ func NewImagePreview(
) (Preview, error) {
dc_size.Store(opts.DiskCacheSize())
ans := &ImagePreview{
abspath: abspath, metadata: metadata, render_channel: make(chan render_data),
abspath: abspath, metadata: metadata, render_channel: make(chan render_data, 1),
WakeupMainThread: WakeupMainThread, renderer: r,
}
if dc, err := preview_cache(); err != nil {

View file

@ -259,13 +259,19 @@ func (pm *PreviewManager) highlight_file_async(path string, output chan highligh
s := style_resolver{light: use_light_colors, syntax_aliases: pm.settings.SyntaxAliases()}
s.light_style, s.dark_style = pm.settings.HighlightStyles()
go func() {
defer func() {
if r := recover(); r != nil {
text, _ := utils.Format_stacktrace_on_panic(r)
debugprintln(fmt.Sprintf("Failed to highlight: %s with panic: %s", path, text))
}
close(output)
pm.WakeupMainThread()
}()
highlighted, err := pm.highlighter.HighlightFile(path, &s)
if err != nil {
debugprintln(fmt.Sprintf("Failed to highlight: %s with error: %s", path, err))
}
output <- highlighed_data{text: highlighted, err: err, light: s.light}
close(output)
pm.WakeupMainThread()
}()
}