summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2024-04-30 15:44:53 +0200
committerFlorian Bruhin <me@the-compiler.org>2024-04-30 17:03:11 +0200
commitb0002ac71f516750e342b5218caf26ef8c7bcec1 (patch)
tree7204d0b5370af1aeb27b0f21084e407ec065834b
parent26ef6bffd261d4ac876bbb35612a5a0b7a6232e7 (diff)
downloadqutebrowser-b0002ac71f516750e342b5218caf26ef8c7bcec1.tar.gz
qutebrowser-b0002ac71f516750e342b5218caf26ef8c7bcec1.zip
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).
-rw-r--r--doc/changelog.asciidoc3
-rw-r--r--qutebrowser/utils/resources.py8
2 files changed, 11 insertions, 0 deletions
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()