Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Better integration of faulthandler. See #1853
Instead of writing the stacktrace to stderr, write it to ~/.quodlibet/faultdump and on the next start raise an exception with the content. Slightly adjust the exception dialog to use a text view for the exception message instead of a tree view header since the passed text from the faulthandler stack trace can be quite long.
- Loading branch information
Showing
6 changed files
with
160 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2016 Christoph Reiter | ||
# | ||
# This program is free software; you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License version 2 as | ||
# published by the Free Software Foundation | ||
|
||
""" | ||
Interface around faulthandler to save and restore segfault info for the | ||
next program invocation. | ||
""" | ||
|
||
import os | ||
import ctypes | ||
import errno | ||
|
||
try: | ||
import faulthandler | ||
except ImportError: | ||
faulthandler = None | ||
|
||
|
||
_fileobj = None | ||
_enabled = False | ||
|
||
|
||
def enable(path): | ||
"""Enable crash reporting and create empty target file | ||
Args: | ||
path (pathlike): the location of the crash log target path | ||
Raises: | ||
IOError: In case the location is not writable | ||
""" | ||
|
||
global _fileobj, _enabled | ||
|
||
if _fileobj is not None: | ||
raise Exception("already enabled") | ||
|
||
_enabled = True | ||
|
||
if faulthandler is None: | ||
return | ||
|
||
try: | ||
_fileobj = open(path, "rb+") | ||
except IOError as e: | ||
if e.errno == errno.ENOENT: | ||
_fileobj = open(path, "wb+") | ||
|
||
faulthandler.enable(_fileobj) | ||
|
||
|
||
def disable(): | ||
"""Disable crash reporting and removes the target file | ||
Does not raise. | ||
""" | ||
|
||
global _fileobj, _enabled | ||
|
||
assert _enabled | ||
_enabled = False | ||
|
||
if _fileobj is None: | ||
return | ||
|
||
faulthandler.disable() | ||
|
||
try: | ||
_fileobj.close() | ||
os.unlink(_fileobj.name) | ||
except IOError: | ||
pass | ||
_fileobj = None | ||
|
||
|
||
def check_and_clear_error(): | ||
"""Returns an error message or None. Calling this will clear the error | ||
so a second call will always return None. | ||
enable() needs to be called first. | ||
Returns: | ||
text or None | ||
Raises: | ||
IOError: In case the file couldn't be read | ||
""" | ||
|
||
global _fileobj, _enabled | ||
|
||
assert _enabled | ||
|
||
if _fileobj is None: | ||
return | ||
|
||
_fileobj.seek(0) | ||
text = _fileobj.read().decode("utf-8", "replace").strip() | ||
_fileobj.seek(0) | ||
_fileobj.truncate() | ||
|
||
if text: | ||
return text | ||
|
||
|
||
def crash(): | ||
"""Makes the process segfault. For testing purposes""" | ||
|
||
ctypes.string_at(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2016 Christoph Reiter | ||
# | ||
# This program is free software; you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License version 2 as | ||
# published by the Free Software Foundation | ||
|
||
from tests import TestCase | ||
from .helper import temp_filename | ||
|
||
from quodlibet.util import faulthandling | ||
|
||
|
||
class Tfaulthandling(TestCase): | ||
|
||
def test_basic(self): | ||
with temp_filename() as filename: | ||
faulthandling.enable(filename) | ||
assert faulthandling.check_and_clear_error() is None | ||
faulthandling.disable() |