summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2022-12-06 18:44:01 +0100
committerFlorian Bruhin <me@the-compiler.org>2022-12-06 18:44:01 +0100
commit6373959824529a0cfa18df53a9d02b0fbe7859a5 (patch)
tree8fab5a42d8c1ac2e11a01281264260df92b404cd
parent7fb15312d0f1fffce1f9675a1f1ab451a6b32869 (diff)
downloadqutebrowser-6373959824529a0cfa18df53a9d02b0fbe7859a5.tar.gz
qutebrowser-6373959824529a0cfa18df53a9d02b0fbe7859a5.zip
Always delay stage 2 shutdown, not only with prompts
If we shut down qutebrowser directly, in some rare situations, we seem to get into some trouble related to a QWidget trying to call into a Q(Common|StyleSheet)Style at shutdown (checking the style hint SH_Widget_ShareActivation, to figure out the palette to use when the window is hidden, or somesuch?). With the recent changes for #7504, those crashes suddenly started happening much more often. After staring at the related changes and gdb for over a day, I still have no idea what actually causes them and why it's crashing - it smells like some kind of PyQt/Qt cleanup order bug... However, what I *did* find out (after a lot of painful debugging and messing around with things) is that delaying the shutdown done from :quit seems to reliably get rid of the issue. I don't know *why*, but I haven't seen it happen anymore with the latest changes... Fixes #5385 and #5124, both speculatively. Closes #7504 since this was the last change required to make it all work.
-rw-r--r--qutebrowser/mainwindow/prompt.py16
-rw-r--r--qutebrowser/misc/quitter.py27
2 files changed, 16 insertions, 27 deletions
diff --git a/qutebrowser/mainwindow/prompt.py b/qutebrowser/mainwindow/prompt.py
index 279721b2a..db7553e7e 100644
--- a/qutebrowser/mainwindow/prompt.py
+++ b/qutebrowser/mainwindow/prompt.py
@@ -131,20 +131,12 @@ class PromptQueue(QObject):
"""Cancel all blocking questions.
Quits and removes all running event loops.
-
- Return:
- True if loops needed to be aborted,
- False otherwise.
"""
- log.prompt.debug("Shutting down with loops {}".format(self._loops))
+ log.prompt.debug(f"Shutting down with loops {self._loops}")
self._shutting_down = True
- if self._loops:
- for loop in self._loops:
- loop.quit()
- loop.deleteLater()
- return True
- else:
- return False
+ for loop in self._loops:
+ loop.quit()
+ loop.deleteLater()
@pyqtSlot(usertypes.Question, bool)
def ask_question(self, question, blocking):
diff --git a/qutebrowser/misc/quitter.py b/qutebrowser/misc/quitter.py
index 92764a3a4..a849aec70 100644
--- a/qutebrowser/misc/quitter.py
+++ b/qutebrowser/misc/quitter.py
@@ -221,21 +221,18 @@ class Quitter(QObject):
status, session))
sessions.shutdown(session, last_window=last_window)
-
- if prompt.prompt_queue.shutdown():
- # If shutdown was called while we were asking a question, we're in
- # a still sub-eventloop (which gets quit now) and not in the main
- # one.
- # This means we need to defer the real shutdown to when we're back
- # in the real main event loop, or we'll get a segfault.
- log.destroy.debug("Deferring real shutdown because question was "
- "active.")
- QTimer.singleShot(0, functools.partial(self._shutdown_2, status,
- is_restart=is_restart))
- else:
- # If we have no questions to shut down, we are already in the real
- # event loop, so we can shut down immediately.
- self._shutdown_2(status, is_restart=is_restart)
+ prompt.prompt_queue.shutdown()
+
+ # If shutdown was called while we were asking a question, we're in
+ # a still sub-eventloop (which gets quit now) and not in the main
+ # one.
+ # But there's also other situations where it's problematic to shut down
+ # immediately (e.g. when we're just starting up).
+ # This means we need to defer the real shutdown to when we're back
+ # in the real main event loop, or we'll get a segfault.
+ log.destroy.debug("Deferring shutdown stage 2")
+ QTimer.singleShot(
+ 0, functools.partial(self._shutdown_2, status, is_restart=is_restart))
def _shutdown_2(self, status: int, is_restart: bool) -> None:
"""Second stage of shutdown."""