Nuitka: Access violation/segmentation fault connecting signal (with `QFileSystemWatcher`/`QTimer`)

Good things come in threes. #2086, #2492, and now this. Note this code likely doesn’t do anything useful anymore, it is highly reduced to reproduce the segmentation fault.

crash.py

# nuitka-project: --onefile
# nuitka-project: --static-libpython=no
# nuitka-project: --enable-plugin=pyside6
# nuitka-project: --nofollow-import-to=tkinter
# possibly remove the above since 1.7
# 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

# With tests:
# 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_crash
# nuitka-project: --nofollow-import-to=doctest
# nuitka-project: --include-data-file=test_crash.py=.

from pathlib import Path

import pytest

if __name__ == "__main__":
    pytest.main([Path(__file__).parent, "-s"], ["pytestqt.plugin"])

test_crash.py

from contextlib import contextmanager, nullcontext

from window import Window


def test_crash(qtbot, tmp_path):
    tmp_file = tmp_path / "tmp_file.raw"

    window = Window(tmp_file)
    qtbot.addWidget(window)

    def write(contents):
        with tmp_file.open("wb") as file:
            file.write(contents.encode("utf-8"))

    @contextmanager
    def wait(fixed=0):
        signal_wait = qtbot.waitSignal(window.signal, timeout=5000)
        with nullcontext() if fixed else signal_wait:
            yield
        if fixed:
            qtbot.wait(fixed)

    write("1")

    with wait():
        window.start()

    with wait(fixed=200):
        write("12")

    with wait():
        qtbot.wait(300)

window.py

from PySide6.QtCore import QFileSystemWatcher, QTimer, Signal
from PySide6.QtWidgets import QMainWindow


class Window(QMainWindow):
    signal = Signal()

    def __init__(self, path):
        super().__init__()
        self.path = path
        self.fsize = self.get_fsize()
        self.watcher = QFileSystemWatcher()
        self.watcher.fileChanged.connect(self.file_changed)

    def get_fsize(self):
        try:
            return self.path.stat().st_size
        except FileNotFoundError:
            return 0

    def file_changed(self):
        if (new_size := self.get_fsize()) != self.fsize:
            self.fsize = new_size
            QTimer.singleShot(300, self.file_changed)
            return
        self.start()

    def start(self):
        self.signal.emit()
        self.watcher.addPath(str(self.path))

Setup:

Python=3.11.6
Nuitka==1.9rc5  # 11a3d44ab12c706a54e85c21d5161e2983e1bc01
PySide6-Essentials==6.5.3
pytest==7.4.2
pytest-qt==4.2.0

Run

pytest  # works
python -m nuitka crash.py
dist-nuitka/crash.bin  # segfaults

Output

====================================================================================== test session starts ======================================================================================platform linux -- Python 3.11.6, pytest-7.4.2, pluggy-1.3.0
PySide6 6.5.3 -- Qt runtime 6.5.3 -- Qt compiled 6.5.3
rootdir: /tmp/onefile_11874_1697322110_687089
collected 1 item

../../../../tmp/onefile_11874_1697322110_687089/test_crash.py Fatal Python error: Segmentation fault

Current thread 0x00007f34dcefab80 (most recent call first):
  File "/tmp/onefile_11874_1697322110_687089/pytestqt/wait_signal.py", line 193 in connect
  File "/tmp/onefile_11874_1697322110_687089/pytestqt/qtbot.py", line 289 in waitSignal
  File "/tmp/onefile_11874_1697322110_687089/test_crash.py", line 18 in wait
  File "/tmp/onefile_11874_1697322110_687089/contextlib.py", line 137 in __enter__
  File "/tmp/onefile_11874_1697322110_687089/test_crash.py", line 32 in test_crash
  File "/tmp/onefile_11874_1697322110_687089/_pytest/python.py", line 194 in pytest_pyfunc_call
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_callers.py", line 27 in _multicall
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_manager.py", line 106 in _hookexec
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_hooks.py", line 479 in __call__
  File "/tmp/onefile_11874_1697322110_687089/_pytest/python.py", line 1792 in runtest
  File "/tmp/onefile_11874_1697322110_687089/_pytest/runner.py", line 169 in pytest_runtest_call
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_callers.py", line 27 in _multicall
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_manager.py", line 106 in _hookexec
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_hooks.py", line 479 in __call__
  File "/tmp/onefile_11874_1697322110_687089/_pytest/runner.py", line 262 in <lambda>
  File "/tmp/onefile_11874_1697322110_687089/_pytest/runner.py", line 341 in from_call
  File "/tmp/onefile_11874_1697322110_687089/_pytest/runner.py", line 261 in call_runtest_hook
  File "/tmp/onefile_11874_1697322110_687089/_pytest/runner.py", line 222 in call_and_report
  File "/tmp/onefile_11874_1697322110_687089/_pytest/runner.py", line 133 in runtestprotocol
  File "/tmp/onefile_11874_1697322110_687089/_pytest/runner.py", line 114 in pytest_runtest_protocol
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_callers.py", line 27 in _multicall
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_manager.py", line 106 in _hookexec
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_hooks.py", line 479 in __call__
  File "/tmp/onefile_11874_1697322110_687089/_pytest/main.py", line 350 in pytest_runtestloop
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_callers.py", line 27 in _multicall
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_manager.py", line 106 in _hookexec
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_hooks.py", line 479 in __call__
  File "/tmp/onefile_11874_1697322110_687089/_pytest/main.py", line 325 in _main
  File "/tmp/onefile_11874_1697322110_687089/_pytest/main.py", line 271 in wrap_session
  File "/tmp/onefile_11874_1697322110_687089/_pytest/main.py", line 318 in pytest_cmdline_main
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_callers.py", line 27 in _multicall
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_manager.py", line 106 in _hookexec
  File "/tmp/onefile_11874_1697322110_687089/pluggy/_hooks.py", line 479 in __call__
  File "/tmp/onefile_11874_1697322110_687089/_pytest/config/__init__.py", line 169 in main

About this issue

  • Original URL
  • State: closed
  • Created 9 months ago
  • Comments: 15 (7 by maintainers)

Most upvoted comments

Interested in seeing if my full app works now, too!

It does! Thanks a lot!