Skip to content

Prevent UI freeze when opening binary files#732

Open
oxidworks wants to merge 1 commit intolinuxmint:masterfrom
oxidworks:fix-binary-file-freeze
Open

Prevent UI freeze when opening binary files#732
oxidworks wants to merge 1 commit intolinuxmint:masterfrom
oxidworks:fix-binary-file-freeze

Conversation

@oxidworks
Copy link
Copy Markdown

Summary

Opening a binary file (e.g. an ELF executable, a .o object, an image) in xed causes 100% CPU usage and a complete UI freeze that can last indefinitely. The only way to recover is to kill the process.

This has been reported multiple times over the past 7+ years (#174, #491, #591, #624) and affects all xed versions using GtkSourceView.

Root cause

Binary files typically contain no newline characters, so the entire file content ends up as a single GtkTextBuffer line. The encoding fallback mechanism (insert_fallback() in GtkSourceView) converts each byte to a 3-character hex escape (\XX), tripling the length. Pango/HarfBuzz text shaping on a line with millions of characters blocks the GTK main thread indefinitely.

A secondary freeze vector exists in update_cursor_position_statusbar() which iterates character-by-character (O(n)) from the start of the line to calculate the column position.

Changes

1. Pre-load binary detection (xed-tab.c)

  • Before starting the GtkSourceFileLoader, checks the content type via g_file_query_info()
  • Falls back to scanning the first 8KB for NUL bytes (reliable binary indicator)
  • Text-like types (text/*, XML, JSON, JavaScript, SVG) are always allowed through
  • If binary is detected: shows a warning info bar instead of loading

2. Binary file warning info bar (xed-io-error-info-bar.c/.h)

  • New xed_binary_file_warning_info_bar_new() function
  • Shows the detected file type description (e.g. "ELF shared library")
  • "Open Anyway" button allows the user to force-open if desired
  • "Don't Open" closes the tab

3. Cursor position optimization (xed-window.c)

  • For lines longer than 10,000 characters, uses gtk_text_iter_get_line_offset() directly instead of the O(n) character-by-character loop
  • Prevents secondary freeze if a user does open a file with very long lines

Testing

  • Opening /usr/bin/xed (binary): warning info bar appears, no freeze
  • Opening normal text files: no change in behavior
  • Opening XML/JSON/SVG files: no false positives
  • "Open Anyway" on a small binary: loads correctly (with hex escapes)

Fixes #491
Fixes #591
Related: #624, #174

Binary files typically contain no newline characters, causing the entire
file content to be placed in a single GtkTextBuffer line. This triggers
extremely slow Pango/HarfBuzz text shaping (O(n²) for varied content)
that blocks the GTK main thread indefinitely at 100% CPU.

The problem is compounded by the encoding fallback mechanism which
converts each byte to a 3-character hex escape (\XX), tripling the
line length.

This commit adds three mitigations:

1. Pre-load binary detection in _xed_tab_load(): Before starting the
   file loader, check the content type via GIO and scan the first 8KB
   for NUL bytes. If the file appears binary, show a warning info bar
   with "Open Anyway" / "Don't Open" buttons instead of loading
   immediately. Text-like types (text/*, XML, JSON, JS, SVG) are
   always allowed through.

2. New xed_binary_file_warning_info_bar_new(): Creates a warning
   info bar showing the detected file type description and explaining
   that opening binary files can cause unresponsiveness.

3. Cursor position optimization in update_cursor_position_statusbar():
   For lines longer than 10,000 characters, use gtk_text_iter_get_line_offset()
   directly instead of the O(n) character-by-character tab-width
   calculation loop. This prevents a secondary freeze vector when the
   cursor moves on very long lines.

Fixes: linuxmint#491
Fixes: linuxmint#591
Related: linuxmint#624
@oxidworks oxidworks force-pushed the fix-binary-file-freeze branch from a937d79 to c8b1ec4 Compare April 4, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant