Nuitka: Access violation/segmentation fault waiting for PySide6 signal
Hi, remember the segfault from #2086? Here we go again, with a different one (I think. I hope. I have no idea). I am aware that you do not recommend bundling pytest, but doing so allows me to properly test the executables I generate (before potentially re-building it without pytest). And it really puts nuitka and PySide6 to a hard test, which maybe you appreciate (or maybe not 😄).
I have already spent a day reducing my 5,000±lines-of-code repository into something that I can post here (that is, < 100 lines, no dependencies except PySide6, pytest, and pytest-qt), and I hope that it may give you some hints in the right direction while I try to reduce further (although it’s getting harder).
This happens only with nuitka, not when running pyinstaller instead, and not when running the code natively. This makes me think nuitka may be to blame. Then again, this happens with PySide6 v6.5.3 and v6.5.2 but not 6.5.1.1 nor 6.5.1 nor 6.5.0. (The diff between these versions is relatively small, at least on the Python side (https://code.qt.io/cgit/pyside/pyside-setup.git/diff/?id=v6.5.2&id2=v6.5.1.1), but it does have the nth try of fixing the infamous PYSIDE-2299:
https://code.qt.io/cgit/pyside/pyside-setup.git/commit/sources/pyside6/libpyside/signalmanager.cpp?id=afffc5838523595ac1625c5e4ae27b99f7e24557). So maybe it’s PySide who is to blame. But it may also be that these kinds of changes just change the memory layout to a degree that it exposes a nuitka bug. I don’t know, I hope that tells you something at least.
Here’s my code. raiser and fallback are inspired by https://github.com/Suor/funcy. I was able to change fallback to a degree that it would not even call fun and still trigger the bug, so I guess those functions are not the core of the issue. But I have a hard time reproducing the issue without them (or SharedMemory, for that matter).
app.py:
# nuitka-project: --onefile
# nuitka-project: --static-libpython=no
# nuitka-project: --enable-plugin=pyside6
# nuitka-project: --nofollow-import-to=tkinter
# nuitka-project: --noinclude-default-mode=error
# nuitka-project-if: {OS} == "Windows":
# nuitka-project: --output-filename=crash.exe
# nuitka-project-if: {OS} == "Linux":
# nuitka-project: --output-filename=crash.bin
# nuitka-project: --output-dir=dist-nuitka
# nuitka-project: --assume-yes-for-downloads
# nuitka-project: --noinclude-pytest-mode=allow
# nuitka-project: --noinclude-unittest-mode=allow
# nuitka-project: --include-package=_pytest
# nuitka-project: --include-package=pytestqt
# nuitka-project: --include-module=PySide6.QtTest
# nuitka-project: --include-module=test.test_crash
# nuitka-project: --nofollow-import-to=doctest
# nuitka-project: --include-data-file=test=test=**/test_*.*
from pathlib import Path
import pytest
pytest.main([Path(__file__).parent.resolve() / "test", "-s"], ["pytestqt.plugin"])
test/test_crash.py
from multiprocessing.shared_memory import SharedMemory
from PySide6.QtCore import Signal
from PySide6.QtWidgets import QMainWindow, QSpinBox
def raiser(exception):
def _raiser():
raise exception
return _raiser
def fallback(*funcs):
for func in funcs:
try:
return func()
except Exception:
pass
class Class:
def __init__(self, test, resource):
self.name = f"{test}_{resource}"
print(f"Class({self.name})")
self.result = fallback(self.fun1, self.fun2, raiser(ConnectionError))
print(f"end of Class({self.name})")
def fun1(self):
print(f"fun1({self.name})")
result = SharedMemory(self.name)
print(f"end of fun1({self.name})")
return result
def fun2(self):
print(f"fun2({self.name})")
result = SharedMemory(self.name, create=True, size=10)
print(f"end of fun2({self.name}) return")
return result
class Window(QMainWindow):
signal = Signal()
def __init__(self, test):
super().__init__()
self.class_a = Class(test, "A")
self.class_b = Class(test, "B")
print("Done with Class")
self.spin_a = QSpinBox()
self.spin_b = QSpinBox()
self.show()
print("Done with Window")
def test_crash1(qtbot):
window = Window("crash1")
qtbot.addWidget(window)
print("Starting to wait")
with qtbot.waitSignal(window.signal):
print("Waiting")
window.signal.emit()
print("Done waiting")
def test_crash2(qtbot):
window = Window("crash2")
qtbot.addWidget(window)
print("Starting to wait")
with qtbot.waitSignal(window.signal):
print("Waiting")
window.signal.emit()
print("Done waiting")
For now, I can reproduce this by running
python -m nuitka app.py && dist-nuitka/crash.bin
The output is like this (structured a bit more for readability):
Class(crash1_A)
fun1(crash1_A)
fun2(crash1_A)
end of fun2(crash1_A) return
end of Class(crash1_A)
Class(crash1_B)
fun1(crash1_B)
fun2(crash1_B)
end of fun2(crash1_B) return
end of Class(crash1_B)
Done with Class
Done with Window
Starting to wait
Waiting
Done waiting
.Class(crash2_A)
fun1(crash2_A)
fun2(crash2_A)
end of fun2(crash2_A) return
end of Class(crash2_A)
Class(crash2_B)
fun1(crash2_B)
fun2(crash2_B)
end of fun2(crash2_B) return
end of Class(crash2_B)
Done with Class
Done with Window
Starting to wait
Waiting
Fatal Python error: Segmentation fault
File "/tmp/onefile_9297_1697139437_767758/pytestqt/wait_signal.py", line 62 in _cleanup
File "/tmp/onefile_9297_1697139437_767758/pytestqt/wait_signal.py", line 223 in _cleanup
File "/tmp/onefile_9297_1697139437_767758/pytestqt/wait_signal.py", line 208 in _quit_loop_by_signal
File "/tmp/onefile_9297_1697139437_767758/test/test_crash.py", line 75 in test_crash2
- Please check out if the develop version of Nuitka works better for you.
No, bac73eae0090563aa0c19a569cb0486002337661 has the same issue.
python -m nuitka --version
1.8.4
Commercial: None
Python: 3.11.6 (main, Oct 6 2023, 21:02:08) [GCC 12.3.0]
Flavor: pyenv
Executable: /home/bers/.pyenv/versions/3.11.6/bin/python3
OS: Linux
Arch: x86_64
Distribution: Ubuntu (based on Debian) 23.04
Version C compiler: /usr/bin/gcc (gcc).
- How did you install Nuitka and Python
pip and pyenv
python -m pip freeze
iniconfig==2.0.0
nuitka==1.8.4
ordered-set==4.1.0
packaging==23.2
pluggy==1.3.0
PySide6-Essentials==6.5.2
pytest==7.4.2
pytest-qt==4.2.0
shiboken6==6.5.2
zstandard==0.21.0
About this issue
- Original URL
- State: closed
- Created 9 months ago
- Comments: 15 (10 by maintainers)
This is now on the develop branch, I didn’t have a chance to look at the other issue yet.
Thanks for your report, this is fixed on the factory branch, which is a development version under rapid development. You can try it out by going here: https://nuitka.net/doc/factory.html
Feedback if this is working is very welcome, just please do not share plans of doing it, but rather confirmations or denials of it working.