utils/memory_leak: factor out count_objects_in_memory
What changed, and why it matters
This is a small internal code cleanup in Electrum's memory-leak debugging utility. It moves an existing object-counting routine into a helper function and changes it to store weak references instead of strong references. There is no user-facing bug fix or security change.
No security action required. Treat as normal maintenance/refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit refactors DebugMem.mem_stats() by extracting the garbage-collection object enumeration into count_objects_in_memory(). The only behavioral change is that the returned mapping now contains weakref.ref objects rather than direct object references. This prevents the debugging tool itself from accidentally keeping objects alive while measuring garbage collection. It is a test/debugging helper, not a security patch.
Changed components
electrum/utils/memory_leak.pyInspect captured patch +20 / −11
diff --git a/electrum/utils/memory_leak.py b/electrum/utils/memory_leak.py
index 2c4026c..06cc3eb 100644
--- a/electrum/utils/memory_leak.py
+++ b/electrum/utils/memory_leak.py
@@ -2,10 +2,29 @@ from collections import defaultdict
import datetime
import os
import time
+from typing import Sequence, Mapping, TypeVar, Optional
+import weakref
from electrum.util import ThreadJob
+_U = TypeVar('_U')
+
+def count_objects_in_memory(mclasses: Sequence[type[_U]]) -> Mapping[type[_U], Sequence[weakref.ref[_U]]]:
+ import gc
+ gc.collect()
+ objmap = defaultdict(list)
+ for obj in gc.get_objects():
+ for class_ in mclasses:
+ try:
+ _isinstance = isinstance(obj, class_)
+ except AttributeError:
+ _isinstance = False
+ if _isinstance:
+ objmap[class_].append(weakref.ref(obj))
+ return objmap
+
+
class DebugMem(ThreadJob):
'''A handy class for debugging GC memory leaks
@@ -21,18 +40,8 @@ class DebugMem(ThreadJob):
self.interval = interval
def mem_stats(self):
- import gc
self.logger.info("Start memscan")
- gc.collect()
- objmap = defaultdict(list)
- for obj in gc.get_objects():
- for class_ in self.classes:
- try:
- _isinstance = isinstance(obj, class_)
- except AttributeError:
- _isinstance = False
- if _isinstance:
- objmap[class_].append(obj)
+ objmap = count_objects_in_memory(self.classes)
for class_, objs in objmap.items():
self.logger.info(f"{class_.__name__}: {len(objs)}")
self.logger.info("Finish memscan")
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.