pyface icon indicating copy to clipboard operation
pyface copied to clipboard

Bug report: Tests halt on Rocky Linux 8 using PySide6-6.7.1

Open itziakos opened this issue 1 year ago • 1 comments
trafficstars

Environment

OS: Linux Python version: 3.11 Toolkit: Qt Qt API: PySide6 6.7.1

Description

Tests halt on (WSL2) Rocky Linux 8 using PySide6-6.7.1. The test run will resume if the pop up windows are closed but similar errors appear later and the run does not finish.

Steps to Reproduce

edm env create test --version 3.11
edm install -e test PySide6 numpy pygments packaging pillow importlib_resources build wheel
edm run -e test -- pip install traits pyface
edm run -e test -- python -m unittest discover pyface

output

test_set_title_change_active_task (pyface.tasks.tests.test_task_window.TestTaskWindow.test_set_title_change_active_task) ... ok
test_set_title_change_active_task_name (pyface.tasks.tests.test_task_window.TestTaskWindow.test_set_title_change_active_task_name) ... ok
test_set_title_change_title (pyface.tasks.tests.test_task_window.TestTaskWindow.test_set_title_change_title) ... ok
test_set_title_no_active_task (pyface.tasks.tests.test_task_window.TestTaskWindow.test_set_title_no_active_task) ... ok
test_set_title_no_tasks (pyface.tasks.tests.test_task_window.TestTaskWindow.test_set_title_no_tasks) ... ok
test_title_activate_task (pyface.tasks.tests.test_task_window.TestTaskWindow.test_title_activate_task) ... ok
test_title_change_active_task (pyface.tasks.tests.test_task_window.TestTaskWindow.test_title_change_active_task) ... ok
test_title_change_active_task_name (pyface.tasks.tests.test_task_window.TestTaskWindow.test_title_change_active_task_name) ... ok
test_title_change_deactivate_task (pyface.tasks.tests.test_task_window.TestTaskWindow.test_title_change_deactivate_task) ... ok
test_title_default (pyface.tasks.tests.test_task_window.TestTaskWindow.test_title_default) ... ok
test_title_no_active_task (pyface.tasks.tests.test_task_window.TestTaskWindow.test_title_no_active_task) ... ok
test_defaults (pyface.tasks.tests.test_tasks_application.TestApplication.test_defaults) ... ok
test_lifecycle (pyface.tasks.tests.test_tasks_application.TestApplication.test_lifecycle) ... Traceback (most recent call last):
  File "/home/itziakos/.edm/envs/build-env/lib/python3.11/site-packages/pyface/ui/qt/gui.py", line 190, in _dispatch
    self._callable(*self._args, **self._kw)
  File "/home/itziakos/.edm/envs/build-env/lib/python3.11/site-packages/pyface/application.py", line 220, in exit
    self._exit()
  File "/home/itziakos/.edm/envs/build-env/lib/python3.11/site-packages/pyface/gui_application.py", line 236, in _exit
    self.gui.stop_event_loop()
    ^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: '_Undefined' object has no attribute 'stop_event_loop'

image

itziakos avatar Jun 12 '24 13:06 itziakos

On WSL2 the tests halt but on linux VM they segfault.

[2024-06-12T15:33:10.219Z] b'test_lifecycle (pyface.tasks.tests.test_tasks_application.TestApplication.test_lifecycle) ... Traceback (most recent call last):'
[2024-06-12T15:33:10.220Z] b'  File "/home/builder/.edm/envs/build-env/lib/python3.11/site-packages/pyface/ui/qt/gui.py", line 190, in _dispatch'
[2024-06-12T15:33:10.220Z] b'    self._callable(*self._args, **self._kw)'
[2024-06-12T15:33:10.220Z] b'  File "/home/builder/.edm/envs/build-env/lib/python3.11/site-packages/pyface/application.py", line 220, in exit'
[2024-06-12T15:33:10.220Z] b'    self._exit()'
[2024-06-12T15:33:10.220Z] b'  File "/home/builder/.edm/envs/build-env/lib/python3.11/site-packages/pyface/gui_application.py", line 236, in _exit'
[2024-06-12T15:33:10.220Z] b'    self.gui.stop_event_loop()'
[2024-06-12T15:33:10.220Z] b'    ^^^^^^^^^^^^^^^^^^^^^^^^'
[2024-06-12T15:33:10.220Z] b"AttributeError: '_Undefined' object has no attribute 'stop_event_loop'"
[2024-06-12T15:33:10.220Z] b'FAIL'
[2024-06-12T15:33:10.220Z] b''
[2024-06-12T15:33:10.220Z] b'======================================================================'
[2024-06-12T15:33:10.220Z] b'FAIL: test2_test_pyside6 (__main__.Tests.test2_test_pyside6)'
[2024-06-12T15:33:10.220Z] b'----------------------------------------------------------------------'
[2024-06-12T15:33:10.220Z] b'Traceback (most recent call last):'
[2024-06-12T15:33:10.220Z] b'  File "/home/builder/workspace/Buildsystem/test/new/cp311/pyface-8.0.0/tests/run.py", line 27, in test2_test_pyside6'
[2024-06-12T15:33:10.220Z] b'    self.runpy(args, env=env)'
[2024-06-12T15:33:10.220Z] b'  File "/home/builder/workspace/Buildsystem/test/new/cp311/entest_utils.py", line 469, in runpy'
[2024-06-12T15:33:10.220Z] b'    self.run_test_function('
[2024-06-12T15:33:10.220Z] b'  File "/home/builder/workspace/Buildsystem/test/new/cp311/entest_utils.py", line 546, in run_test_function'
[2024-06-12T15:33:10.220Z] b'    self.fail("unexpected test exit code {!r}".format(ret))'
[2024-06-12T15:33:10.220Z] b'AssertionError: unexpected test exit code -15'
[2024-06-12T15:33:10.220Z] b''
[2024-06-12T15:33:10.220Z] b'----------------------------------------------------------------------'
[2024-06-12T15:33:10.220Z] b'Ran 18 tests in 1180.661s'
[2024-06-12T15:33:10.220Z] b''
[2024-06-12T15:33:10.220Z] b'FAILED (failures=1, skipped=11)'
[2024-06-12T15:33:10.220Z] b'================================================='
[2024-06-12T15:33:10.220Z] b"ENTEST STOP -- TOTAL FAILURES: 1 ('pyface-8.0.0')"

itziakos avatar Jun 13 '24 11:06 itziakos

I think there's a race condition in these tests: they do a self.invoke_after(1000, app.exit), and as a result app.exit is getting invoked during application startup, before the gui trait of the application has been set.

I'm able to reproduce locally; running just this one test by itself using python -m unittest pyface.tasks.tests.test_tasks_application.TestApplication.test_lifecycle, the test sometimes passed and sometimes fails. If I change the 1000 to 10000, it always passes, while if I change the 1000 to 100 it almost always fails.

mdickinson avatar Feb 11 '25 16:02 mdickinson

I think there's a race condition in these tests: they do a self.invoke_after(1000, app.exit), and as a result app.exit is getting invoked during application startup, before the gui trait of the application has been set.

In more detail: the GuiApplication.start method is responsible for setting the gui attribute. If start is successful, the Application.run method then fires the "started" event. So it should be enough to make sure that we don't invoke app.exit until after thestarted event has fired.

mdickinson avatar May 15 '25 10:05 mdickinson