Move quitter/signal/crash_handler out of qApp.
This commit is contained in:
parent
564a589bc6
commit
3b5b49daac
@ -66,8 +66,22 @@ def run(args):
|
|||||||
print(version.GPL_BOILERPLATE.strip())
|
print(version.GPL_BOILERPLATE.strip())
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
quitter = Quitter(args)
|
||||||
|
objreg.register('quitter', quitter)
|
||||||
|
|
||||||
global qApp
|
global qApp
|
||||||
qApp = Application(args)
|
qApp = Application(args)
|
||||||
|
qApp.lastWindowClosed.connect(quitter.on_last_window_closed)
|
||||||
|
|
||||||
|
crash_handler = crashsignal.CrashHandler(
|
||||||
|
app=qApp, quitter=quitter, args=args, parent=qApp)
|
||||||
|
crash_handler.activate()
|
||||||
|
objreg.register('crash-handler', crash_handler)
|
||||||
|
|
||||||
|
signal_handler = crashsignal.SignalHandler(app=qApp, quitter=quitter,
|
||||||
|
parent=qApp)
|
||||||
|
signal_handler.activate()
|
||||||
|
objreg.register('signal-handler', signal_handler)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sent = ipc.send_to_running_instance(args.command)
|
sent = ipc.send_to_running_instance(args.command)
|
||||||
@ -93,7 +107,7 @@ def run(args):
|
|||||||
# We didn't really initialize much so far, so we just quit hard.
|
# We didn't really initialize much so far, so we just quit hard.
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
init(args)
|
init(args, crash_handler)
|
||||||
ret = qt_mainloop()
|
ret = qt_mainloop()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -107,8 +121,13 @@ def qt_mainloop():
|
|||||||
return qApp.exec_()
|
return qApp.exec_()
|
||||||
|
|
||||||
|
|
||||||
def init(args):
|
def init(args, crash_handler):
|
||||||
"""Initialize everything."""
|
"""Initialize everything.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args: The argparse namespace.
|
||||||
|
crash_handler: The CrashHandler instance.
|
||||||
|
"""
|
||||||
log.init.debug("Starting init...")
|
log.init.debug("Starting init...")
|
||||||
qApp.setQuitOnLastWindowClosed(False)
|
qApp.setQuitOnLastWindowClosed(False)
|
||||||
qApp.setOrganizationName("qutebrowser")
|
qApp.setOrganizationName("qutebrowser")
|
||||||
@ -118,7 +137,7 @@ def init(args):
|
|||||||
utils.actute_warning()
|
utils.actute_warning()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_init_modules(args)
|
_init_modules(args, crash_handler)
|
||||||
except (OSError, UnicodeDecodeError) as e:
|
except (OSError, UnicodeDecodeError) as e:
|
||||||
msgbox = QMessageBox(
|
msgbox = QMessageBox(
|
||||||
QMessageBox.Critical, "Error while initializing!",
|
QMessageBox.Critical, "Error while initializing!",
|
||||||
@ -143,7 +162,7 @@ def init(args):
|
|||||||
QDesktopServices.setUrlHandler('qute', open_desktopservices_url)
|
QDesktopServices.setUrlHandler('qute', open_desktopservices_url)
|
||||||
|
|
||||||
log.init.debug("Init done!")
|
log.init.debug("Init done!")
|
||||||
qApp.crash_handler.raise_crashdlg()
|
crash_handler.raise_crashdlg()
|
||||||
|
|
||||||
|
|
||||||
def _init_icon():
|
def _init_icon():
|
||||||
@ -342,8 +361,13 @@ def _maybe_hide_mouse_cursor():
|
|||||||
qApp.restoreOverrideCursor()
|
qApp.restoreOverrideCursor()
|
||||||
|
|
||||||
|
|
||||||
def _init_modules(args):
|
def _init_modules(args, crash_handler):
|
||||||
"""Initialize all 'modules' which need to be initialized."""
|
"""Initialize all 'modules' which need to be initialized.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args: The argparse namespace.
|
||||||
|
crash_handler: The CrashHandler instance.
|
||||||
|
"""
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
log.init.debug("Initializing save manager...")
|
log.init.debug("Initializing save manager...")
|
||||||
save_manager = savemanager.SaveManager(qApp)
|
save_manager = savemanager.SaveManager(qApp)
|
||||||
@ -362,7 +386,7 @@ def _init_modules(args):
|
|||||||
log.init.debug("Initializing web history...")
|
log.init.debug("Initializing web history...")
|
||||||
history.init(qApp)
|
history.init(qApp)
|
||||||
log.init.debug("Initializing crashlog...")
|
log.init.debug("Initializing crashlog...")
|
||||||
qApp.crash_handler.handle_segfault()
|
crash_handler.handle_segfault()
|
||||||
log.init.debug("Initializing sessions...")
|
log.init.debug("Initializing sessions...")
|
||||||
sessions.init(qApp)
|
sessions.init(qApp)
|
||||||
log.init.debug("Initializing js-bridge...")
|
log.init.debug("Initializing js-bridge...")
|
||||||
@ -573,6 +597,9 @@ class Quitter:
|
|||||||
def _shutdown(self, status): # noqa
|
def _shutdown(self, status): # noqa
|
||||||
"""Second stage of shutdown."""
|
"""Second stage of shutdown."""
|
||||||
log.destroy.debug("Stage 2 of shutting down...")
|
log.destroy.debug("Stage 2 of shutting down...")
|
||||||
|
if qApp is None:
|
||||||
|
# No QApplication exists yet, so quit hard.
|
||||||
|
sys.exit(status)
|
||||||
# Remove eventfilter
|
# Remove eventfilter
|
||||||
try:
|
try:
|
||||||
log.destroy.debug("Removing eventfilter...")
|
log.destroy.debug("Removing eventfilter...")
|
||||||
@ -602,14 +629,14 @@ class Quitter:
|
|||||||
"Error while saving {}: {}".format(key, e))
|
"Error while saving {}: {}".format(key, e))
|
||||||
msgbox.exec_()
|
msgbox.exec_()
|
||||||
# Re-enable faulthandler to stdout, then remove crash log
|
# Re-enable faulthandler to stdout, then remove crash log
|
||||||
log.destroy.debug("Deactiving crash log...")
|
log.destroy.debug("Deactivating crash log...")
|
||||||
qApp.crash_handler.destroy_crashlogfile()
|
objreg.get('crash-handler').destroy_crashlogfile()
|
||||||
# If we don't kill our custom handler here we might get segfaults
|
# If we don't kill our custom handler here we might get segfaults
|
||||||
log.destroy.debug("Deactiving message handler...")
|
log.destroy.debug("Deactiving message handler...")
|
||||||
qInstallMessageHandler(None)
|
qInstallMessageHandler(None)
|
||||||
# Now we can hopefully quit without segfaults
|
# Now we can hopefully quit without segfaults
|
||||||
log.destroy.debug("Deferring QApplication::exit...")
|
log.destroy.debug("Deferring QApplication::exit...")
|
||||||
qApp.signal_handler.deactivate()
|
objreg.get('signal-handler').deactivate()
|
||||||
# We use a singleshot timer to exit here to minimize the likelihood of
|
# We use a singleshot timer to exit here to minimize the likelihood of
|
||||||
# segfaults.
|
# segfaults.
|
||||||
QTimer.singleShot(0, functools.partial(qApp.exit, status))
|
QTimer.singleShot(0, functools.partial(qApp.exit, status))
|
||||||
@ -630,11 +657,7 @@ class Application(QApplication):
|
|||||||
"""Main application instance.
|
"""Main application instance.
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
quitter: The Quitter objet.
|
|
||||||
crash_handler: The CrashHandler being used.
|
|
||||||
signal_handler: The SignalHandler being used.
|
|
||||||
_args: ArgumentParser instance.
|
_args: ArgumentParser instance.
|
||||||
_shutting_down: True if we're currently shutting down.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
@ -648,17 +671,6 @@ class Application(QApplication):
|
|||||||
super().__init__(qt_args)
|
super().__init__(qt_args)
|
||||||
|
|
||||||
log.init.debug("Initializing application...")
|
log.init.debug("Initializing application...")
|
||||||
self.quitter = Quitter(args)
|
|
||||||
self.lastWindowClosed.connect(self.quitter.on_last_window_closed)
|
|
||||||
objreg.register('quitter', self.quitter)
|
|
||||||
|
|
||||||
self.crash_handler = crashsignal.CrashHandler(app=self, args=args,
|
|
||||||
parent=self)
|
|
||||||
self.crash_handler.activate()
|
|
||||||
objreg.register('crash-handler', self.crash_handler)
|
|
||||||
|
|
||||||
self.signal_handler = crashsignal.SignalHandler(app=self, parent=self)
|
|
||||||
self.signal_handler.activate()
|
|
||||||
|
|
||||||
self._args = args
|
self._args = args
|
||||||
objreg.register('args', args)
|
objreg.register('args', args)
|
||||||
|
@ -43,14 +43,16 @@ class CrashHandler(QObject):
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
_app: The QApplication instance.
|
_app: The QApplication instance.
|
||||||
|
_quitter: The Quitter instance.
|
||||||
_args: The argparse namespace.
|
_args: The argparse namespace.
|
||||||
_crash_dialog: The CrashDialog currently being shown.
|
_crash_dialog: The CrashDialog currently being shown.
|
||||||
_crash_log_file: The file handle for the faulthandler crash log.
|
_crash_log_file: The file handle for the faulthandler crash log.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, app, args, parent=None):
|
def __init__(self, *, app, quitter, args, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._app = app
|
self._app = app
|
||||||
|
self._quitter = quitter
|
||||||
self._args = args
|
self._args = args
|
||||||
self._crash_log_file = None
|
self._crash_log_file = None
|
||||||
self._crash_dialog = None
|
self._crash_dialog = None
|
||||||
@ -160,7 +162,7 @@ class CrashHandler(QObject):
|
|||||||
exc = (exctype, excvalue, tb)
|
exc = (exctype, excvalue, tb)
|
||||||
qapp = QApplication.instance()
|
qapp = QApplication.instance()
|
||||||
|
|
||||||
if not qapp.quitter.quit_status['crash']:
|
if not self._quitter.quit_status['crash']:
|
||||||
log.misc.error("ARGH, there was an exception while the crash "
|
log.misc.error("ARGH, there was an exception while the crash "
|
||||||
"dialog is already shown:", exc_info=exc)
|
"dialog is already shown:", exc_info=exc)
|
||||||
return
|
return
|
||||||
@ -185,7 +187,7 @@ class CrashHandler(QObject):
|
|||||||
qapp.quit()
|
qapp.quit()
|
||||||
return
|
return
|
||||||
|
|
||||||
qapp.quitter.quit_status['crash'] = False
|
self._quitter.quit_status['crash'] = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pages = self._recover_pages(forgiving=True)
|
pages = self._recover_pages(forgiving=True)
|
||||||
@ -212,7 +214,7 @@ class CrashHandler(QObject):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self._app.lastWindowClosed.disconnect(
|
self._app.lastWindowClosed.disconnect(
|
||||||
self._app.quitter.on_last_window_closed)
|
self._quitter.on_last_window_closed)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
log.destroy.exception("Error while preventing shutdown")
|
log.destroy.exception("Error while preventing shutdown")
|
||||||
self._app.closeAllWindows()
|
self._app.closeAllWindows()
|
||||||
@ -220,7 +222,7 @@ class CrashHandler(QObject):
|
|||||||
self._args.debug, pages, cmd_history, exc, objects)
|
self._args.debug, pages, cmd_history, exc, objects)
|
||||||
ret = self._crash_dialog.exec_()
|
ret = self._crash_dialog.exec_()
|
||||||
if ret == QDialog.Accepted: # restore
|
if ret == QDialog.Accepted: # restore
|
||||||
self._app.quitter.restart(pages)
|
self._quitter.restart(pages)
|
||||||
|
|
||||||
# We might risk a segfault here, but that's better than continuing to
|
# We might risk a segfault here, but that's better than continuing to
|
||||||
# run in some undefined state, so we only do the most needed shutdown
|
# run in some undefined state, so we only do the most needed shutdown
|
||||||
@ -241,6 +243,7 @@ class SignalHandler(QObject):
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
_app: The QApplication instance.
|
_app: The QApplication instance.
|
||||||
|
_quitter: The Quitter instance.
|
||||||
_activated: Whether activate() was called.
|
_activated: Whether activate() was called.
|
||||||
_notifier: A QSocketNotifier used for signals on Unix.
|
_notifier: A QSocketNotifier used for signals on Unix.
|
||||||
_timer: A QTimer used to poll for signals on Windows.
|
_timer: A QTimer used to poll for signals on Windows.
|
||||||
@ -248,9 +251,10 @@ class SignalHandler(QObject):
|
|||||||
_orig_wakeup_fd: The original wakeup filedescriptor.
|
_orig_wakeup_fd: The original wakeup filedescriptor.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, app, parent=None):
|
def __init__(self, *, app, quitter, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._app = app
|
self._app = app
|
||||||
|
self._quitter = quitter
|
||||||
self._notifier = None
|
self._notifier = None
|
||||||
self._timer = usertypes.Timer(self, 'python_hacks')
|
self._timer = usertypes.Timer(self, 'python_hacks')
|
||||||
self._orig_handlers = {}
|
self._orig_handlers = {}
|
||||||
@ -330,7 +334,7 @@ class SignalHandler(QObject):
|
|||||||
signal.signal(signal.SIGTERM, self.interrupt_forcefully)
|
signal.signal(signal.SIGTERM, self.interrupt_forcefully)
|
||||||
# If we call shutdown directly here, we get a segfault.
|
# If we call shutdown directly here, we get a segfault.
|
||||||
QTimer.singleShot(0, functools.partial(
|
QTimer.singleShot(0, functools.partial(
|
||||||
self._app.quitter.shutdown, 128 + signum))
|
self._quitter.shutdown, 128 + signum))
|
||||||
|
|
||||||
def interrupt_forcefully(self, signum, _frame):
|
def interrupt_forcefully(self, signum, _frame):
|
||||||
"""Interrupt forcefully on the second SIGINT/SIGTERM request.
|
"""Interrupt forcefully on the second SIGINT/SIGTERM request.
|
||||||
|
Loading…
Reference in New Issue
Block a user