harvimt / quamash

Implementation of the PEP 3156 event-loop (asyncio) api using the Qt Event-Loop
BSD 2-Clause "Simplified" License
264 stars 46 forks source link

Event filter + dialogs cause the application to crash #103

Closed rr- closed 5 years ago

rr- commented 5 years ago

Using Quamash 0.6.1.

Consider the following program, that opens a dialog window within the main event loop, and uses a global event filter:

#!/usr/bin/env python3
import asyncio
import sys
import typing as T

from PyQt5 import QtCore, QtWidgets
from quamash import QEventLoop

async def show_error(msg: str) -> int:
    dialog = QtWidgets.QMessageBox()
    dialog.setIcon(QtWidgets.QMessageBox.Critical)
    dialog.setWindowTitle("Error")
    dialog.setText(msg)
    future: "asyncio.Future[int]" = asyncio.Future()
    dialog.finished.connect(lambda result: future.set_result(result))
    dialog.open()
    return await future

class Window(QtWidgets.QWidget):
    def __init__(self) -> None:
        super().__init__()
        self.setLayout(QtWidgets.QHBoxLayout())
        self.button = QtWidgets.QPushButton("Ready", parent=self)
        self.button.clicked.connect(self.on_button_click)
        self.layout().addWidget(self.button)
        QtWidgets.QApplication.instance().installEventFilter(self)

    def on_button_click(self) -> None:
        asyncio.ensure_future(show_error("test"))

    def eventFilter(
        self, source: QtCore.QObject, event: QtCore.QEvent
    ) -> bool:
        print(source, event, event.type())
        return False

def main() -> None:
    app = QtWidgets.QApplication(sys.argv)
    loop = QEventLoop(app)
    asyncio.set_event_loop(loop)
    window = Window()
    window.show()
    with loop:
        loop.run_forever()

if __name__ == "__main__":
    main()

Here's what happens – I'm getting a rather cryptic error in Python's internals:

test

StopIteration: 1024

The above exception was the direct cause of the following exception:

SystemError: <class 'PyQt5.QtWidgets.QWidget'> returned a result with an error set
zsh: abort (core dumped)  python3 test
rr- commented 5 years ago

Figured it out. My issue was caused by QMessageBox having set no parent widget. Passing window to it has fixed the problem.