Handle multi-instance better with crash.log
This commit is contained in:
parent
93ce283ec9
commit
f97c87628b
@ -107,7 +107,8 @@ class QuteBrowser(QApplication):
|
|||||||
self._quit_status = {
|
self._quit_status = {
|
||||||
'crash': True,
|
'crash': True,
|
||||||
'tabs': False,
|
'tabs': False,
|
||||||
'networkmanager': False
|
'networkmanager': False,
|
||||||
|
'main': False,
|
||||||
}
|
}
|
||||||
self._timers = []
|
self._timers = []
|
||||||
self._opened_urls = []
|
self._opened_urls = []
|
||||||
@ -249,23 +250,54 @@ class QuteBrowser(QApplication):
|
|||||||
|
|
||||||
def _handle_segfault(self):
|
def _handle_segfault(self):
|
||||||
"""Handle a segfault from a previous run."""
|
"""Handle a segfault from a previous run."""
|
||||||
|
# FIXME If an empty logfile exists, we log to stdout instead, which is
|
||||||
|
# the only way to not break multiple instances.
|
||||||
|
# However this also means if the logfile is there for some weird
|
||||||
|
# reason, we'll *always* log to stderr, but that's still better than no
|
||||||
|
# dialogs at all.
|
||||||
logname = os.path.join(get_standard_dir(QStandardPaths.DataLocation),
|
logname = os.path.join(get_standard_dir(QStandardPaths.DataLocation),
|
||||||
'crash.log')
|
'crash.log')
|
||||||
# First check if an old logfile exists.
|
# First check if an old logfile exists.
|
||||||
if os.path.exists(logname):
|
if os.path.exists(logname):
|
||||||
with open(logname, 'r') as f:
|
with open(logname, 'r') as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
# Just in case FatalCrashDialog crashes... -.-
|
|
||||||
os.remove(logname)
|
|
||||||
if data:
|
if data:
|
||||||
|
# Crashlog exists and has data in it, so something crashed
|
||||||
|
# previously.
|
||||||
|
try:
|
||||||
|
os.remove(logname)
|
||||||
|
except PermissionError:
|
||||||
|
logging.warn("Could not remove crash log!")
|
||||||
|
else:
|
||||||
|
self._init_crashlogfile()
|
||||||
self._crashdlg = FatalCrashDialog(data)
|
self._crashdlg = FatalCrashDialog(data)
|
||||||
self._crashdlg.show()
|
self._crashdlg.show()
|
||||||
# Start a new logfile and redirect faulthandler to it
|
else:
|
||||||
self._crashlogfile = open(logname, 'w') # This also truncates.
|
# Crashlog exists but without data.
|
||||||
|
# This means another instance is probably still running and
|
||||||
|
# didn't remove the file. As we can't write to the same file,
|
||||||
|
# we just leave faulthandler as it is and log to stderr.
|
||||||
|
logging.warn("Empty crash.log detected. This means either "
|
||||||
|
"another instance is running (then ignore this "
|
||||||
|
"warning) or the file is lying here because "
|
||||||
|
"of some earlier crash (then delete it).")
|
||||||
|
self._crashlogfile = None
|
||||||
|
else:
|
||||||
|
# There's no log file, so we can use this to display crashes to the
|
||||||
|
# user on the next start.
|
||||||
|
self._init_crashlogfile()
|
||||||
|
|
||||||
|
def _init_crashlogfile(self):
|
||||||
|
"""Start a new logfile and redirect faulthandler to it."""
|
||||||
|
logname = os.path.join(get_standard_dir(QStandardPaths.DataLocation),
|
||||||
|
'crash.log')
|
||||||
|
self._crashlogfile = open(logname, 'w')
|
||||||
faulthandler.enable(self._crashlogfile)
|
faulthandler.enable(self._crashlogfile)
|
||||||
if hasattr(faulthandler, 'register') and hasattr(signal, 'SIGUSR1'):
|
if (hasattr(faulthandler, 'register') and
|
||||||
|
hasattr(signal, 'SIGUSR1')):
|
||||||
# If available, we also want a traceback on SIGUSR1.
|
# If available, we also want a traceback on SIGUSR1.
|
||||||
faulthandler.register(signal.SIGUSR1) # pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
|
faulthandler.register(signal.SIGUSR1)
|
||||||
|
|
||||||
def _init_cmds(self):
|
def _init_cmds(self):
|
||||||
"""Initialisation of the qutebrowser commands.
|
"""Initialisation of the qutebrowser commands.
|
||||||
@ -595,6 +627,15 @@ class QuteBrowser(QApplication):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
logging.exception("No networkmanager to shut down.")
|
logging.exception("No networkmanager to shut down.")
|
||||||
self._maybe_quit('networkmanager')
|
self._maybe_quit('networkmanager')
|
||||||
|
if self._crashlogfile is not None:
|
||||||
|
# Re-enable faulthandler to stdout, then remove crash log
|
||||||
|
faulthandler.enable()
|
||||||
|
self._crashlogfile.close()
|
||||||
|
try:
|
||||||
|
os.remove(self._crashlogfile.name)
|
||||||
|
except PermissionError:
|
||||||
|
pass
|
||||||
|
self._maybe_quit('main')
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_tab_shutdown_complete(self):
|
def on_tab_shutdown_complete(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user