enthought / enthought/traitsui
Reference leak from simple editor
- Dominant language
- Python
- Stars
- 306
- Forks
- 99
- PR merge metrics
- No merged PRs in 30d
Description
[Derived from enthought/traits#1164]
Meta: I'm not sure whether this issue belongs in TraitsUI or Pyface, but the relevant code appears to be in Pyface.
Opening and closing a simple TraitsUI editor leaks Python references (but not gc-tracked Python objects).
Here's a script that can be used to reproduce. It needs a debug build of Python, for the `sys.gettotalrefcount` function. On my machine, under Python 3.8, with a `pip`-installed Pyface, PyQt5 and other dependencies, it shows a leak of 30 references per iteration, but the total number of gc-tracked objects stays stable. However, amongst the tracked objects I can only see a reference count increase of 8 per iteration, suggesting that there _are_ untracked objects being leaked.
I'd say this is likely related to PyQt5, except that the script also behaves badly on PySide2. This may be a sign that there's some cleanup somewhere that we should be doing, but aren't (for example, making sure that signals that are connected are always eventually disconnected).
```python
import gc
import sys
from traits.api import HasTraits, Int
from pyface.qt.QtGui import QApplication
from pyface.ui.qt4.gui import GUI
from pyface.ui.qt4.util.event_loop_helper import EventLoopHelper
class EnumCollectionExample(HasTraits):
letters = Int()
def create_and_destroy_editor():
qt_app = QApplication.instance()
if qt_app is None:
qt_app = QApplication([])
gui = GUI()
event_loop_helper = EventLoopHelper(qt_app=qt_app, gui=gui)
# Create and destroy a UI window
obj = EnumCollectionExample()
ui = obj.edit_traits()
try:
gui.process_events()
finally:
with event_loop_helper.delete_widget(ui.control, timeout=10.0):
ui.dispose()
event_loop_helper.event_loop_with_timeout(repeat=5, timeout=10.0)
qt_app.flush()
def main():
for _ in range(20):
create_and_destroy_editor()
while gc.collect():
pass
print("Total refcount: ", sys.gettotalrefcount())
if __name__ == "__main__":
main()
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.