Ultimaker / Uranium

A Python framework for building Desktop applications.
GNU Lesser General Public License v3.0
327 stars 185 forks source link

Segmentation fault on tests/TaskManagement/TestHttpRequestManager.py::test_getBasicAuthSuccess #594

Open ggardet opened 4 years ago

ggardet commented 4 years ago

With Uranium 4.5.0, I get the following test failure:

[   85s] tests/TaskManagement/TestHttpRequestManager.py::test_getBasicAuthSuccess Fatal Python error: Segmentation fault
[   85s] 
[   85s] Thread 0x00007f1721ffb700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f17227fc700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f1722ffd700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f17237fe700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f1723fff700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f1744ff9700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f17457fa700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f1745ffb700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f17467fc700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f1746ffd700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f17477fe700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f1747fff700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f175cff9700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f175d7fa700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f175dffb700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f175e7fc700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f175effd700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f175f7fe700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f175ffff700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/threading.py", line 302 in wait
[   85s]   File "/usr/lib64/python3.8/threading.py", line 433 in acquire
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 86 in _nextJob
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/UM/JobQueue.py", line 112 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Thread 0x00007f1771471700 (most recent call first):
[   85s]   File "/usr/lib64/python3.8/site-packages/twisted/internet/epollreactor.py", line 218 in doPoll
[   85s]   File "/usr/lib64/python3.8/site-packages/twisted/internet/base.py", line 1295 in mainLoop
[   85s]   File "/usr/lib64/python3.8/site-packages/twisted/internet/base.py", line 1283 in run
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/tests/TaskManagement/conftest.py", line 113 in _runServer
[   85s]   File "/usr/lib64/python3.8/threading.py", line 870 in run
[   85s]   File "/usr/lib64/python3.8/threading.py", line 932 in _bootstrap_inner
[   85s]   File "/usr/lib64/python3.8/threading.py", line 890 in _bootstrap
[   85s] 
[   85s] Current thread 0x00007f1781e5a740 (most recent call first):
[   85s]   File "/home/abuild/rpmbuild/BUILD/Uranium-4.5.0/tests/TaskManagement/TestHttpRequestManager.py", line 121 in test_getBasicAuthSuccess
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/python.py", line 167 in pytest_pyfunc_call
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/callers.py", line 187 in _multicall
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 84 in <lambda>
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 93 in _hookexec
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/hooks.py", line 286 in __call__
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/python.py", line 1445 in runtest
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/runner.py", line 134 in pytest_runtest_call
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/callers.py", line 187 in _multicall
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 84 in <lambda>
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 93 in _hookexec
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/hooks.py", line 286 in __call__
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/runner.py", line 210 in <lambda>
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/runner.py", line 237 in from_call
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/runner.py", line 209 in call_runtest_hook
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/runner.py", line 185 in call_and_report
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/runner.py", line 99 in runtestprotocol
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/runner.py", line 84 in pytest_runtest_protocol
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/callers.py", line 187 in _multicall
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 84 in <lambda>
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 93 in _hookexec
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/hooks.py", line 286 in __call__
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/main.py", line 271 in pytest_runtestloop
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/callers.py", line 187 in _multicall
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 84 in <lambda>
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 93 in _hookexec
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/hooks.py", line 286 in __call__
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/main.py", line 247 in _main
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/main.py", line 197 in wrap_session
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/main.py", line 240 in pytest_cmdline_main
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/callers.py", line 187 in _multicall
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 84 in <lambda>
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/manager.py", line 93 in _hookexec
[   85s]   File "/usr/lib/python3.8/site-packages/pluggy/hooks.py", line 286 in __call__
[   85s]   File "/usr/lib/python3.8/site-packages/_pytest/config/__init__.py", line 92 in main
[   85s]   File "/usr/lib/python3.8/site-packages/pytest/__main__.py", line 7 in <module>
[   85s]   File "/usr/lib64/python3.8/runpy.py", line 86 in _run_code
[   85s]   File "/usr/lib64/python3.8/runpy.py", line 193 in _run_module_as_main
[   85s] /var/tmp/rpm-tmp.3rmbmI: line 30:  2336 Segmentation fault      python3 -m pytest -v
Ghostkeeper commented 4 years ago

I'm unable to reproduce this. The tests succeed for me, apart from the typing check which fails on Trust.py for me locally (as I have a more modern version of Mypy than our CI server).

The line in question is app.exec() on a QCoreApplication:

https://github.com/Ultimaker/Uranium/blob/a0de6788a771bf494e945aa3a8ab50dbfdcec353/tests/TaskManagement/TestHttpRequestManager.py#L121

So that means that somewhere Qt is getting a segfault. That should never happen. We may need to bump this up to Qt or Riverbank.

gferon commented 4 years ago

I'm trying to package python-uranium for cura 4.5 and 4.6 for Fedora, and I'm getting the same segfault. I'm currently trying to investigate but came to the same conclusion as you did @Ghostkeeper (that it should never happen).

EDIT: what's suspicious is the test pass when executed one by one, which makes me think somewhere there's global state that makes them failing when running the entire suite.

Ghostkeeper commented 4 years ago

Maybe something in PyQt then? It looks like it creates multiple QCoreApplication instances within the same run of Python now (due to other tests creating one too). Maybe they don't properly get destroyed afterwards, or they indeed alter some global state in Qt somewhere?

You could try to move that QCoreApplication to a singleton, maybe, but the tests call the function quit() on it too so that could spell trouble.

StefanBruens commented 4 years ago

I would never expect to be able to create and destroy QCoreApplication multiple times. One QCoreApplication seems the much better option, maybe with a QEventLoop for each test if multiple event loops are deemed necessary.

Ghostkeeper commented 4 years ago

The application is re-created for every test in order to prevent previous tests from influencing subsequent tests. If they did, that would create some particularly nasty bugs in the tests that are hard to track down. Those bugs would also be exclusive to the tests, so fixing them is not making the application any better.

For me though and our CI server, this destroying and re-creating works fine. The Qt framework should allow that sort of thing.

StefanBruens commented 4 years ago

The application is re-created for every test in order to prevent previous tests from influencing subsequent tests.

Then you should also restart the python runtime, because it may contain some leftover state. Recreating the HttpRequestsManager should be completely sufficient.

If they did, that would create some particularly nasty bugs in the tests that are hard to track down. Those bugs would also be exclusive to the tests, so fixing them is not making the application any better.

You do not recreate the QApplication in the real application, so why do you do in the tests? If deleting the application were a requirement to make requests independent, then the tests would succeed, but the same requests in the real application would fail because there is some leftover state.

For me though and our CI server, this destroying and re-creating works fine. The Qt framework should allow that sort of thing.

Which version of Qt are you using? Have you tested Qt 5.12 and Qt 5.15, which are the current LTS releases? (And Qt 5.15 will be the last Qt5 version ever.)

Ghostkeeper commented 4 years ago

Yeah, we should restart the Python runtime, but that's not how PyTest works. Understandably, most unit tests wouldn't need this sort of thing and they'd claim that tests are expected to clean up after themselves.

Which version of Qt are you using?

We're currently on Qt 5.10.2. This is necessary to support some old MacOS versions that we still have a lot of users on. As that is dwindling though, we have a mind to upgrade to 5.12, which would solve a few open bugs (in particular a nasty one that crashes Cura if people use different GPUs for different screens).

StefanBruens commented 4 years ago

So, how about:

  1. One QApplication fixture with session scope - resembles actual usage in cura
  2. Make sure the manager does not leak state, i.e. tests still pass.

I could spend a little bit of time on this, iff this is deemed a sensible route forward and able to be merged.

Ghostkeeper commented 4 years ago

Yeah that is probably the only way to fix this.

The difficulty is probably in the 2nd point there. The HttpRequestManager in particular uses multithreading so you could end up with nondeterministic tests pretty quickly.