From b0002ac71f516750e342b5218caf26ef8c7bcec1 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 30 Apr 2024 15:44:53 +0200 Subject: Preload broken qutebrowser logo resource When qutebrowser is running but its installation has been deleted/moved, it fails in somewhat mysterious but predictable ways. This is e.g. the case currently, when people upgrade their Archlinux packages and upgrade from Python 3.11 to 3.12. When doing that with qutebrowser open, on the next page load, it will: - Have a crashed renderer process, because (assumingly) the process executable is gone on disk. - Which then causes us trying to render an error page, but that fails due to broken_qutebrowser_logo.png being gone from disk. - The FileNotFoundError then causes jinja2 to import jinja2.debug at runtime, but that *also* fails because the jinja2 package is gone. We work around this by loading the PNG into RAM early, and then using the cached version instead. This amends b4a2352833bfb06c86c1afb8b088cead0ef7c6d5 which did the same with HTML/JS resources, but never for this PNG, which (looking at crash logs) seems to be a somewhat common breakage. Alternatives I've considered: - Catching the FileNotFoundError and not showing an error page at all. - Generating a PNG with an explanatory text via QPainter and returning that. However, with the renderer process crash happening in the first place for unknown reasons, it's unclear if the error page ever gets actually displayed... Let's roll with this for now, and if this causes a repeating renderer process crash, fix that separately (also see #5108). --- doc/changelog.asciidoc | 3 +++ qutebrowser/utils/resources.py | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/doc/changelog.asciidoc b/doc/changelog.asciidoc index b6385b015..e90c84a31 100644 --- a/doc/changelog.asciidoc +++ b/doc/changelog.asciidoc @@ -47,6 +47,9 @@ Fixed condition. - Worked around qutebrowser quitting when closing a KDE file dialog due to a Qt bug. +- Worked around a crash when trying to use qutebrowser after it's been + deleted/moved on disk (e.g. after a Python upgrade). It now shows an error + asking to run `:restart` instead. [[v3.1.1]] v3.1.1 (unreleased) diff --git a/qutebrowser/utils/resources.py b/qutebrowser/utils/resources.py index a40f9d2bd..a97a2e994 100644 --- a/qutebrowser/utils/resources.py +++ b/qutebrowser/utils/resources.py @@ -26,6 +26,7 @@ else: # pragma: no cover import qutebrowser _cache: Dict[str, str] = {} +_bin_cache: Dict[str, bytes] = {} _ResourceType = Union[Traversable, pathlib.Path] @@ -88,6 +89,10 @@ def preload() -> None: for name in _glob(resource_path, subdir, ext): _cache[name] = read_file(name) + for name in _glob(resource_path, 'img', '.png'): + # e.g. broken_qutebrowser_logo.png + _bin_cache[name] = read_file_binary(name) + def read_file(filename: str) -> str: """Get the contents of a file contained with qutebrowser. @@ -115,6 +120,9 @@ def read_file_binary(filename: str) -> bytes: Return: The file contents as a bytes object. """ + if filename in _bin_cache: + return _bin_cache[filename] + path = _path(filename) with _keyerror_workaround(): return path.read_bytes() -- cgit v1.2.3-54-g00ecf