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.
This commit is contained in:
parent
7fb15312d0
commit
6373959824
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -221,21 +221,18 @@ class Quitter(QObject):
|
|||
status, session))
|
||||
|
||||
sessions.shutdown(session, last_window=last_window)
|
||||
prompt.prompt_queue.shutdown()
|
||||
|
||||
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)
|
||||
# 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."""
|
||||
|
|
|
|||
Loading…
Reference in New Issue