1
0

crash reporter: only show reporter once per exception groupid

- don't show crash reporter multiple times for the "same" exception
  - at least until the user restart the program (there is no persistence)
- this is a ~replacement for the removed "Never show crash reporter" option
- in case there e.g. a thread with timer spamming an exception erroneously,
  this ensures we only offer to send the crash report once (per process lifecycle)
This commit is contained in:
SomberNight
2025-07-18 16:34:54 +00:00
parent 0e0e47c3c5
commit c85272b546
3 changed files with 22 additions and 0 deletions

View File

@@ -33,6 +33,7 @@ from . import constants
from .i18n import _
from .util import make_aiohttp_session, error_text_str_to_safe_str
from .logging import describe_os_version, Logger, get_git_version
from .crypto import sha256
if TYPE_CHECKING:
from .network import ProxySettings
@@ -140,6 +141,17 @@ class BaseCrashReporter(Logger):
"id": _id,
}
@classmethod
def get_traceback_groupid_hash(
cls,
exctype: type[BaseException],
excvalue: BaseException,
tb: TracebackType | None,
) -> bytes:
tb_info = cls.get_traceback_info(exctype, excvalue, tb)
_id = tb_info["id"]
return sha256(str(_id))
def get_additional_info(self):
args = {
"app_version": get_git_version() or ELECTRUM_VERSION,

View File

@@ -537,6 +537,7 @@ class Exception_Hook(QObject, Logger):
Logger.__init__(self)
assert self._INSTANCE is None, "Exception_Hook is supposed to be a singleton"
self.wallet_types_seen = set() # type: Set[str]
self.exception_ids_seen = set() # type: Set[bytes]
sys.excepthook = self.handler
threading.excepthook = self.handler
@@ -554,4 +555,8 @@ class Exception_Hook(QObject, Logger):
def handler(self, *exc_info):
self.logger.error('exception caught by crash reporter', exc_info=exc_info)
groupid_hash = BaseCrashReporter.get_traceback_groupid_hash(*exc_info)
if groupid_hash in self.exception_ids_seen:
return # to avoid annoying the user, only show crash reporter once per exception groupid
self.exception_ids_seen.add(groupid_hash)
self._report_exception.emit(*exc_info)

View File

@@ -177,6 +177,7 @@ class Exception_Hook(QObject, Logger):
assert self._INSTANCE is None, "Exception_Hook is supposed to be a singleton"
self.config = config
self.wallet_types_seen = set() # type: Set[str]
self.exception_ids_seen = set() # type: Set[bytes]
sys.excepthook = self.handler
self._report_exception.connect(_show_window)
@@ -191,6 +192,10 @@ class Exception_Hook(QObject, Logger):
def handler(self, *exc_info):
self.logger.error('exception caught by crash reporter', exc_info=exc_info)
groupid_hash = BaseCrashReporter.get_traceback_groupid_hash(*exc_info)
if groupid_hash in self.exception_ids_seen:
return # to avoid annoying the user, only show crash reporter once per exception groupid
self.exception_ids_seen.add(groupid_hash)
self._report_exception.emit(self.config, *exc_info)