Handle exceptions with a crash dialog.
This commit is contained in:
parent
a71684ea0f
commit
2c276b98a4
@ -1,7 +1,9 @@
|
||||
""" Initialization of qutebrowser and application-wide things """
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
import traceback
|
||||
import faulthandler
|
||||
from signal import signal, SIGINT
|
||||
from argparse import ArgumentParser
|
||||
@ -12,12 +14,13 @@ from argparse import ArgumentParser
|
||||
import qutebrowser.utils.harfbuzz as harfbuzz
|
||||
harfbuzz.fix()
|
||||
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
from PyQt5.QtWidgets import QApplication, QDialog
|
||||
from PyQt5.QtCore import QUrl, QTimer
|
||||
|
||||
import qutebrowser.commands.utils as cmdutils
|
||||
import qutebrowser.utils.config as config
|
||||
from qutebrowser.widgets.mainwindow import MainWindow
|
||||
from qutebrowser.widgets import CrashDialog
|
||||
from qutebrowser.commands.keys import KeyParser
|
||||
from qutebrowser.utils.appdirs import AppDirs
|
||||
|
||||
@ -107,32 +110,57 @@ class QuteBrowser(QApplication):
|
||||
fallback='http://ddg.gg/').split(','):
|
||||
self.mainwindow.tabs.tabopen(url)
|
||||
|
||||
def _tmp_exception_hook(self, exctype, value, traceback):
|
||||
def _tmp_exception_hook(self, exctype, excvalue, tb):
|
||||
"""Handle exceptions while initializing by simply exiting.
|
||||
|
||||
This is only temporary and will get replaced by exception_hook later.
|
||||
It's necessary because PyQt seems to ignore exceptions by default.
|
||||
"""
|
||||
sys.__excepthook__(exctype, value, traceback)
|
||||
sys.__excepthook__(exctype, excvalue, tb)
|
||||
self.exit(1)
|
||||
|
||||
def _exception_hook(self, exctype, value, traceback):
|
||||
def _exception_hook(self, exctype, excvalue, tb):
|
||||
"""Handle uncaught python exceptions.
|
||||
|
||||
It'll try very hard to write all open tabs to a file, and then exit
|
||||
gracefully.
|
||||
"""
|
||||
# pylint: disable=broad-except
|
||||
sys.__excepthook__(exctype, value, traceback)
|
||||
|
||||
exc = (exctype, excvalue, tb)
|
||||
traceback.print_exception(*exc)
|
||||
|
||||
pages = []
|
||||
try:
|
||||
for tabidx in range(self.mainwindow.tabs.count()):
|
||||
try:
|
||||
# FIXME write to some file
|
||||
print(self.mainwindow.tabs.widget(tabidx).url().url())
|
||||
url = self.mainwindow.tabs.widget(tabidx).url().toString()
|
||||
url = url.strip()
|
||||
if url:
|
||||
pages.append(url)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
history = self.mainwindow.status.cmd.history[-5:]
|
||||
except Exception:
|
||||
history = []
|
||||
|
||||
dlg = CrashDialog(pages, history, exc)
|
||||
ret = dlg.exec_()
|
||||
if ret == QDialog.Accepted: # restore
|
||||
os.environ['PYTHONPATH'] = os.pathsep.join(sys.path)
|
||||
# FIXME we might want to use argparse's features to not open pages
|
||||
# again if they were opened via cmdline
|
||||
argv = [sys.executable] + sys.argv + pages
|
||||
logging.debug('Running {} with args {}'.format(sys.executable,
|
||||
argv))
|
||||
sys.stdout.flush()
|
||||
# FIXME this seems broken on Windows, execv() splits on whitespace
|
||||
# in arguments?!?
|
||||
os.execv(sys.executable, argv)
|
||||
self.exit(1)
|
||||
|
||||
def _python_hacks(self):
|
||||
|
@ -1 +1,59 @@
|
||||
"""The Qt widgets needed by qutebrowser."""
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from PyQt5.QtWidgets import (QDialog, QLabel, QTextEdit, QVBoxLayout,
|
||||
QHBoxLayout, QPushButton)
|
||||
|
||||
import qutebrowser.utils as utils
|
||||
|
||||
|
||||
class CrashDialog(QDialog):
|
||||
"""Dialog which gets shown after there was a crash."""
|
||||
|
||||
def __init__(self, pages, cmdhist, exc):
|
||||
super().__init__()
|
||||
self.setFixedSize(500, 350)
|
||||
self.setWindowTitle('Whoops!')
|
||||
|
||||
vbox = QVBoxLayout()
|
||||
lbl = QLabel(self)
|
||||
#lbl.setGeometry(5, 5, 395, 295)
|
||||
lbl.setText(
|
||||
'Argh! qutebrowser crashed unexpectedly.<br/>'
|
||||
'Please review the info below to remove sensitive data and then '
|
||||
'submit it to '
|
||||
'<a href="mailto:me@the-compiler.org">me@the-compiler.org</a>.'
|
||||
'<br/><br/>You can click "Restore tabs" to attempt to reopen your '
|
||||
'open pages.'
|
||||
)
|
||||
vbox.addWidget(lbl)
|
||||
|
||||
txt = QTextEdit(self)
|
||||
txt.setReadOnly(True)
|
||||
#txt.setGeometry(5, 400, 395, 295)
|
||||
txt.setText(
|
||||
'==== Version info ====\n{}\n\n'.format(utils.version()) +
|
||||
'==== Exception ====\n{}\n'.format(
|
||||
''.join(traceback.format_exception(*exc))) +
|
||||
'==== Open pages ====\n{}\n\n'.format('\n'.join(pages)) +
|
||||
'==== Command history ====\n{}\n\n'.format('\n'.join(cmdhist)) +
|
||||
'==== Commandline args ====\n{}'.format(' '.join(sys.argv[1:]))
|
||||
)
|
||||
vbox.addWidget(txt)
|
||||
self.setLayout(vbox)
|
||||
|
||||
hbox = QHBoxLayout()
|
||||
btn_quit = QPushButton(self)
|
||||
btn_quit.setText('Quit')
|
||||
btn_quit.clicked.connect(self.reject)
|
||||
hbox.addWidget(btn_quit)
|
||||
btn_restore = QPushButton(self)
|
||||
btn_restore.setText('Restore tabs')
|
||||
btn_restore.clicked.connect(self.accept)
|
||||
btn_restore.setDefault(True)
|
||||
hbox.addWidget(btn_restore)
|
||||
|
||||
vbox.addLayout(hbox)
|
||||
self.show()
|
||||
|
Loading…
Reference in New Issue
Block a user