Merge pull request #1800 from phw/PICARD-1718-crash-handler

PICARD-1718: crash handler
This commit is contained in:
Philipp Wolfer
2021-05-07 16:17:06 +02:00
committed by GitHub
3 changed files with 66 additions and 4 deletions

View File

@@ -88,3 +88,50 @@ api_versions = [
]
api_versions_tuple = [Version.from_string(v) for v in api_versions]
def crash_handler():
"""Implements minimal handling of an exception crashing the application.
This function tries to log the exception to a log file and display
a minimal crash dialog to the user.
This function is supposed to be called from inside an except blog.
"""
# First try to get traceback information and write it to a log file
# with minimum chance to fail.
import sys
from tempfile import NamedTemporaryFile
import traceback
trace = traceback.format_exc()
logfile = None
try:
with NamedTemporaryFile(suffix='.log', prefix='picard-crash-', delete=False) as f:
f.write(trace.encode(errors="replace"))
logfile = f.name
except: # noqa: E722,F722 # pylint: disable=bare-except
print("Failed writing log file {0}".format(logfile), file=sys.stderr)
logfile = None
# Display the crash information to the user as a dialog. This requires
# importing Qt5 and has some potential to fail if things are broken.
from PyQt5.QtCore import QCoreApplication, Qt, QUrl
from PyQt5.QtWidgets import QApplication, QMessageBox
app = QCoreApplication.instance()
if not app:
app = QApplication(sys.argv)
msgbox = QMessageBox()
msgbox.setIcon(QMessageBox.Critical)
msgbox.setWindowTitle("Picard terminated unexpectedly")
msgbox.setTextFormat(Qt.RichText)
msgbox.setText(
'An unexpected error has caused Picard to crash. '
'Please report this issue on the <a href="https://tickets.metabrainz.org/projects/PICARD">MusicBrainz bug tracker</a>.')
if logfile:
logfile_url = QUrl.fromLocalFile(logfile)
msgbox.setInformativeText(
'A logfile has been written to <a href="{0}">{1}</a>.'
.format(logfile_url.url(), logfile))
msgbox.setDetailedText(trace)
msgbox.setStandardButtons(QMessageBox.Close)
msgbox.setDefaultButton(QMessageBox.Close)
msgbox.exec_()
app.quit()

View File

@@ -1,3 +1,11 @@
#!/usr/bin/env python3
from picard.tagger import main
main('%(localedir)s', %(autoupdate)s)
try:
from picard.tagger import main
main('%(localedir)s', %(autoupdate)s)
except SystemExit:
raise # Just continue with a normal application exit
except: # noqa: E722,F722 # pylint: disable=bare-except
from picard import crash_handler
crash_handler()
raise

View File

@@ -15,5 +15,12 @@ else:
if sys.platform == 'win32':
os.environ['PATH'] = basedir + ';' + os.environ['PATH']
from picard.tagger import main
main(os.path.join(basedir, 'locale'), %(autoupdate)s)
try:
from picard.tagger import main
main(os.path.join(basedir, 'locale'), %(autoupdate)s)
except SystemExit:
raise # Just continue with a normal application exit
except: # noqa: E722,F722 # pylint: disable=bare-except
from picard import crash_handler
crash_handler()
raise