summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2022-12-06 12:22:09 +0100
committerFlorian Bruhin <me@the-compiler.org>2022-12-06 12:22:09 +0100
commit7b90fd37378853ed47153463298db66a3a98ecac (patch)
treef569d6b7175fb8be176872bc0033b62d24afe90d
parent3f5febf227d746ef9b9b1c90a0110c6e8c23cb3c (diff)
downloadqutebrowser-7b90fd37378853ed47153463298db66a3a98ecac.tar.gz
qutebrowser-7b90fd37378853ed47153463298db66a3a98ecac.zip
Use a proper @pyqtSlot for FilenamePrompt
In bleeding tests, we started to get a segfault on the second test in tests/unit/mainwindow/test_prompt.py, with a stacktrace like: Thread 1 "python" received signal SIGSEGV, Segmentation fault. 0x00007ffff7b55912 in _PyFunction_Vectorcall (func=<function at remote 0x7fffc4368ca0>, stack=0x7fffd74656a8, nargsf=<optimized out>, kwnames=0x0) at Objects/call.c:341 341 if (((PyCodeObject *)f->fc_code)->co_flags & CO_OPTIMIZED) { (gdb) bt #0 0x00007ffff7b55912 in _PyFunction_Vectorcall (func=<function at remote 0x7fffc4368ca0>, stack=0x7fffd74656a8, nargsf=<optimized out>, kwnames=0x0) at Objects/call.c:341 #1 0x00007ffff4e0b3f1 in PyQtSlot::call(_object*, _object*) const (this=0x555556c759c0, args=('/tmp/pytest-of-florian/pytest-70/test_simple_completion_1_next_0/test',), callable=<function at remote 0x7fffc4368ca0>) at ../../qpy/QtCore/qpycore_pyqtslot.cpp:247 #2 PyQtSlot::invoke(void**, _object*, void*, bool) const (this=0x555556c759c0, qargs=<optimized out>, qargs@entry=0x7fffffff86c0, self=<optimized out>, self@entry=0x0, result=result@entry=0x0, no_receiver_check=<optimized out>) at ../../qpy/QtCore/qpycore_pyqtslot.cpp:159 #3 0x00007ffff4e12213 in PyQtSlot::invoke(void**, bool) const (no_receiver_check=<optimized out>, qargs=0x7fffffff86c0, this=<optimized out>) at ../../qpy/QtCore/qpycore_pyqtslot.cpp:78 #4 PyQtSlotProxy::unislot(void**) (qargs=0x7fffffff86c0, this=0x555557193e20) at ../../qpy/QtCore/qpycore_pyqtslotproxy.cpp:205 #5 PyQtSlotProxy::unislot(void**) (qargs=0x7fffffff86c0, this=0x555557193e20) at ../../qpy/QtCore/qpycore_pyqtslotproxy.cpp:186 #6 PyQtSlotProxy::qt_metacall(QMetaObject::Call, int, void**) (this=0x555557193e20, _c=<optimized out>, _id=0, _a=0x7fffffff86c0) at ../../qpy/QtCore/qpycore_pyqtslotproxy.cpp:170 #7 0x00007ffff48bd91d in doActivate<false>(QObject*, int, void**) (sender=0x555556b3d680, signal_index=28, argv=0x7fffffff86c0) at kernel/qobject.cpp:3945 #8 0x00007fffeff96aca in QFileSystemModel::directoryLoaded(QString const&) (this=<optimized out>, _t1=<optimized out>) at .moc/moc_qfilesystemmodel.cpp:272 #9 0x00007ffff48b0be0 in QObject::event(QEvent*) (this=this@entry=0x555556b3d680, e=e@entry=0x7fff0c004af0) at kernel/qobject.cpp:1347 #10 0x00007fffeff962ab in QFileSystemModel::event(QEvent*) (this=this@entry=0x555556b3d680, event=event@entry=0x7fff0c004af0) at dialogs/qfilesystemmodel.cpp:1748 #11 0x00007ffff070995c in sipQFileSystemModel::event(QEvent*) (this=0x555556b3d680, a0=0x7fff0c004af0) at /usr/src/debug/pyqt5/PyQt5-5.15.7/build/QtWidgets/sipQtWidgetsQFileSystemModel.cpp:376 [...] #23 0x00007ffff4da94ce in meth_QCoreApplication_processEvents(PyObject*, PyObject*, PyObject*) (sipArgs=<optimized out>, sipKwds=0x0) at /usr/src/debug/pyqt5/PyQt5-5.15.7/build/QtCore/sipQtCoreQCoreApplication.cpp:590 [...] from pytest-qt in Python: Current thread 0x00007fb366207740 (most recent call first): File ".../pytestqt/plugin.py", line 209 in _process_events File ".../pytestqt/plugin.py", line 171 in pytest_runtest_setup [...] File ".../pytest/src/_pytest/runner.py", line 115 in pytest_runtest_protocol [...] File ".../pytest/src/_pytest/main.py", line 317 in pytest_cmdline_main [...] Introduced by this change in pytest, which now deletes the temporary directory after the test by default: https://github.com/pytest-dev/pytest/pull/10517 It sounds like something odd like the directory removal causing (Py)Qt to call the lambda, but the underlying Python object already being gone or something along those lines. With a proper Qt slot (@pyqtSlot), PyQt seems to do the right thing, so let's just use that instead...
-rw-r--r--qutebrowser/mainwindow/prompt.py18
1 files changed, 15 insertions, 3 deletions
diff --git a/qutebrowser/mainwindow/prompt.py b/qutebrowser/mainwindow/prompt.py
index 5d3bced59..c5acaabda 100644
--- a/qutebrowser/mainwindow/prompt.py
+++ b/qutebrowser/mainwindow/prompt.py
@@ -760,9 +760,21 @@ class FilenamePrompt(_BasePrompt):
self._file_view.setColumnHidden(col, True)
# Nothing selected initially
self._file_view.setCurrentIndex(QModelIndex())
- # The model needs to be sorted so we get the correct first/last index
- self._file_model.directoryLoaded.connect(
- lambda: self._file_model.sort(0))
+
+ self._file_model.directoryLoaded.connect(self.on_directory_loaded)
+
+ @pyqtSlot()
+ def on_directory_loaded(self):
+ """Sort the model after a directory gets loaded.
+
+ The model needs to be sorted so we get the correct first/last index.
+
+ NOTE: This needs to be a proper @pystSlot() function, and not a lambda.
+ Otherwise, PyQt seems to fail to disconnect it immediately after the
+ object gets destroyed, and we get segfaults when deleting the directory
+ in unit tests.
+ """
+ self._file_model.sort(0)
def accept(self, value=None, save=False):
self._check_save_support(save)