Re: Crash-on-exit after call to app.processEvents()
Raymond Osborn <[email protected]> Mon, 25 May 2020 22:51:54 -0500
| Newsgroups | gmane.comp.python.pyqt-pykde |
|---|---|
| Message-ID | <[email protected]> |
--Apple-Mail=_86D63170-33FC-4FEE-A4B7-1F54C6016110 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Armando, I=E2=80=99m writing again because I=E2=80=99ve learned a couple of = useful things that might be worth sharing. I had a scare when the = problem started occurring again for no apparent reason, using the same = sequence I had tested before. I decided to look more closely in the = debugger and discovered that the exit process never fully completed if = one of the windows that had been resized following a processEvents() = call was still open. Somewhere between the =E2=80=98event.accept()=E2=80=99= call in the main window=E2=80=99s closeEvent function and completing = the app._exec() call, it just quit, sometimes with a segfault, sometimes = without.=20 The offending windows had all been opened with the main window as = parent, but when I made them top-level windows, the exit process = completed successfully. I had tried that already before contacting the = mailing list. I think the combination of opening the offending windows = without a parent and then closing all top-level widgets, as you = suggested, may have finally fixed the problem.=20 Not sure if that=E2=80=99s the final word though. Thanks again, Ray > On May 25, 2020, at 5:42 PM, Thomas Caswell <[email protected]> = wrote: >=20 > This is reminding me of the issues Armando raised with Matplotlib = (https://github.com/matplotlib/matplotlib/issues/14178 = <https://github.com/matplotlib/matplotlib/issues/14178> / = https://github.com/matplotlib/matplotlib/pull/14179 = <https://github.com/matplotlib/matplotlib/pull/14179>). I now = understand why Matplotlib (and IPython) holding references to the qApp = can be problematic (as in this case del ing app just drops your = reference to it but does not actually trigger the `__delete__` code = because other parts of the codebase are keeping it alive) if having a = "live" app on process shut down can cause problems. >=20 > My naive guess as to why calling `ProcessEvents` triggers the issue as = that it creates some extra state on at least the c++ side and we end up = tearing down the objects on the Python side in a different order than we = need to on the c++ side. Oventually something winds up with a null = pointer (because there was a reference at the c++ level but not at the = Python level) and boom. I stress that while that is where I would start = looking to track this down it is still very much a guess. >=20 > Tom >=20 > On Mon, May 25, 2020 at 5:36 PM Raymond Osborn <[email protected] = <mailto:[email protected]>> wrote: > Hi Armando, > Good to hear from you. I thought for a while that I had managed to fix = it with the following code : >=20 > def main(filename=3DNone): > app =3D NXConsoleApp() > app.initialize(filename=3Dfilename) > app.start() > for w in QApplication.topLevelWindows(): > del w > del app.window, app.app > sys.exit(0) >=20 > It proved to be a false dawn - the problem started to recur again. = I=E2=80=99ll see if your version catches things that mine missed, and = let you know. >=20 > I have spent a lot of time trying to cover up PyQt5 bugs in the past = year. The problem is that I can=E2=80=99t guarantee that my users will = have the latest version of PyQt, so even if it is fixed in v5.14, I = still have to patch the code. I just have no idea why simply calling = processEvents() triggers the bug. If I knew that, perhaps it would give = some clue how to work around it. >=20 > Ray >=20 >=20 >> On May 25, 2020, at 3:38 PM, V. Armando Sole <[email protected] = <mailto:[email protected]>> wrote: >>=20 >> Hi Ray, >>=20 >> I do not know if it will help your case. I was getting rid of some = crashes on exit by deleting all widgets that had no parent. For = instance, when closing the QMainWindow by doing: >>=20 >> def closeEvent(self, event): >> if __name__ =3D=3D "__main__": >> app =3D qt.QApplication.instance() >> allWidgets =3D app.allWidgets() >> for widget in allWidgets: >> try: >> # we cannot afford to crash here >> if id(widget) !=3D id(self): >> if widget.parent() is None: >> widget.close() >> except: >> _logger.debug("Error closing widget") >> return qt.QMainWindow.closeEvent(self, event) >>=20 >> Best regards, >>=20 >> Armando >>=20 >> On 25.05.2020 19:48, Raymond Osborn wrote: >>=20 >>> I added a call to QtWidgets.QApplication.instance().processEvents() = in order to force adjustResize() to work when switching tabs (that's = another story). It succeeded in fixing my resize issue, but now it = triggers a segfault when I exit the application. This seemed to be = related to the bug described in = https://www.riverbankcomputing.com/static/Docs/PyQt5/gotchas.html#crashes-= on-exit = <https://www.riverbankcomputing.com/static/Docs/PyQt5/gotchas.html#crashes= -on-exit>. One fix, suggested by @ekhumoro on stackoverflow = (https://stackoverflow.com/questions/59120337/why-does-pyqt-sometimes-cras= h-on-exit = <https://stackoverflow.com/questions/59120337/why-does-pyqt-sometimes-cras= h-on-exit>) was to delete the main window and the app first, but that = doesn't seem to fix it. I am running PyQt 5.12 because that is the last = version supported by conda, so I can't test the one-exit fix in v5.13, = and my users probably wouldn't have it installed anyway. It happens on = Macs and linux. >>> =20 >>> What I am asking is if there are additional things to try in = addition to @ekhumoro's suggestion? Basically he suggests doing = something like: >>> =20 >>> def main(): >>> app =3D QApplication(sys.argv) >>> main_window =3D MainWindow() >>> main_window.show() >>> app.exec_() >>> # ensure correct deletion order >>> del main_window, app >>> Does anyone understand why the crash only occurs if I have calls to = processEvents() in the code? It never happens when I remove them. >>> =20 >>> Thanks, >>> Ray >>> =20 >>> =20 >=20 >=20 >=20 > --=20 > Thomas Caswell > [email protected] <mailto:[email protected]> --Apple-Mail=_86D63170-33FC-4FEE-A4B7-1F54C6016110 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8 <html><head><meta http-equiv=3D"Content-Type" content=3D"text/html; = charset=3Dutf-8"></head><body style=3D"word-wrap: break-word; = -webkit-nbsp-mode: space; line-break: after-white-space;" class=3D""><div = class=3D"">Armando,</div><div class=3D"">I=E2=80=99m writing again = because I=E2=80=99ve learned a couple of useful things that might be = worth sharing. I had a scare when the problem started occurring again = for no apparent reason, using the same sequence I had tested before. I = decided to look more closely in the debugger and discovered that the = exit process never fully completed if one of the windows that had been = resized following a processEvents() call was still open. Somewhere = between the =E2=80=98event.accept()=E2=80=99 call in the main window=E2=80= =99s closeEvent function and completing the app._exec() call, it just = quit, sometimes with a segfault, sometimes without. </div><div = class=3D""><br class=3D""></div><div class=3D"">The offending windows = had all been opened with the main window as parent, but when I made them = top-level windows, the exit process completed successfully. I had tried = that already before contacting the mailing list. I think the combination = of opening the offending windows without a parent and then closing all = top-level widgets, as you suggested, may have finally fixed the = problem. </div><div class=3D""><br class=3D""></div><div = class=3D"">Not sure if that=E2=80=99s the final word though.</div><div = class=3D""><br class=3D""></div><div class=3D"">Thanks again,</div><div = class=3D"">Ray</div><div class=3D""><div><br class=3D""><blockquote = type=3D"cite" class=3D""><div class=3D"">On May 25, 2020, at 5:42 PM, = Thomas Caswell <<a href=3D"mailto:[email protected]" = class=3D"">[email protected]</a>> wrote:</div><br = class=3D"Apple-interchange-newline"><div class=3D""><div dir=3D"ltr" = class=3D"">This is reminding me of the issues Armando raised with = Matplotlib (<a = href=3D"https://github.com/matplotlib/matplotlib/issues/14178" = class=3D"">https://github.com/matplotlib/matplotlib/issues/14178</a> = / <a href=3D"https://github.com/matplotlib/matplotlib/pull/14179" = class=3D"">https://github.com/matplotlib/matplotlib/pull/14179</a>). = I now understand why Matplotlib (and IPython) holding references to the = qApp can be problematic (as in this case del ing app just drops your = reference to it but does not actually trigger the `__delete__` code = because other parts of the codebase are keeping it alive) if having = a "live" app on process shut down can cause problems.<div class=3D""><br = class=3D""></div><div class=3D"">My naive guess as to why calling = `ProcessEvents` triggers the issue as that it creates some extra state = on at least the c++ side and we end up tearing down the objects on the = Python side in a different order than we need to on the c++ side. = Oventually something winds up with a null pointer (because there was a = reference at the c++ level but not at the Python level) and boom. = I stress that while that is where I would start looking to track this = down it is still very much a guess.<br class=3D""><div class=3D""><div = class=3D""><br class=3D""><div = class=3D"">Tom</div></div></div></div></div><br class=3D""><div = class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Mon, May = 25, 2020 at 5:36 PM Raymond Osborn <<a = href=3D"mailto:[email protected]" class=3D"">[email protected]</a>> = wrote:<br class=3D""></div><blockquote class=3D"gmail_quote" = style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid = rgb(204,204,204);padding-left:1ex"><div style=3D"overflow-wrap: = break-word;" class=3D"">Hi Armando,<div class=3D"">Good to hear from = you. I thought for a while that I had managed to fix it with the = following code :</div><div class=3D""><br class=3D""></div><div = class=3D""><div class=3D""> def = main(filename=3DNone):</div><div class=3D""> = app =3D NXConsoleApp()</div><div class=3D""> = app.initialize(filename=3Dfilename)</div><div class=3D""> = app.start()</div><div class=3D""> = for w in QApplication.topLevelWindows():</div><div = class=3D""> del w</div><div = class=3D""> del app.window, app.app</div><div = class=3D""> sys.exit(0)</div><div = class=3D""><br class=3D""></div><div class=3D"">It proved to be a false = dawn - the problem started to recur again. I=E2=80=99ll see if your = version catches things that mine missed, and let you know.</div><div = class=3D""><br class=3D""></div><div class=3D"">I have spent a lot of = time trying to cover up PyQt5 bugs in the past year. The problem is that = I can=E2=80=99t guarantee that my users will have the latest version of = PyQt, so even if it is fixed in v5.14, I still have to patch the code. I = just have no idea why simply calling processEvents() triggers the bug. = If I knew that, perhaps it would give some clue how to work around = it.</div><div class=3D""><br class=3D""></div><div = class=3D"">Ray</div><div class=3D""><br class=3D""></div><div = class=3D""><br class=3D""><blockquote type=3D"cite" class=3D""><div = class=3D"">On May 25, 2020, at 3:38 PM, V. Armando Sole <<a = href=3D"mailto:[email protected]" target=3D"_blank" = class=3D"">[email protected]</a>> wrote:</div><br class=3D""><div = class=3D""><div = style=3D"font-size:10pt;font-family:Verdana,Geneva,sans-serif" = class=3D""><p class=3D"">Hi Ray,</p><p class=3D"">I do not know if it = will help your case. I was getting rid of some crashes on exit by = deleting all widgets that had no parent. For instance, when closing the = QMainWindow by doing:</p><p class=3D""> def = closeEvent(self, event):<br = class=3D""> if __name__ =3D=3D = "__main__":<br = class=3D""> &nb= sp; app =3D qt.QApplication.instance()<br = class=3D""> &nb= sp; allWidgets =3D app.allWidgets()<br = class=3D""> &nb= sp; for widget in allWidgets:<br = class=3D""> &nb= sp; try:<br = class=3D""> &nb= sp; # we cannot afford = to crash here<br = class=3D""> &nb= sp; if id(widget) !=3D = id(self):<br = class=3D""> &nb= sp;  = ; if widget.parent() is None:<br = class=3D""> &nb= sp;  = ; widget.close()<br = class=3D""> &nb= sp; except:<br = class=3D""> &nb= sp; _logger.debug("Error = closing widget")<br class=3D""> = return qt.QMainWindow.closeEvent(self, event)</p><p class=3D"">Best = regards,</p><p class=3D"">Armando</p><p class=3D"">On 25.05.2020 19:48, = Raymond Osborn wrote:</p> <blockquote type=3D"cite" style=3D"padding:0px 0.4em;border-left:2px = solid rgb(16,16,255);margin:0px" class=3D"">I added a call = to QtWidgets.QApplication.instance().processEvents() in order to = force adjustResize() to work when switching tabs (that's another story). = It succeeded in fixing my resize issue, but now it triggers a segfault = when I exit the application. This seemed to be related to the bug = described in <a = href=3D"https://www.riverbankcomputing.com/static/Docs/PyQt5/gotchas.html#= crashes-on-exit" target=3D"_blank" = class=3D"">https://www.riverbankcomputing.com/static/Docs/PyQt5/gotchas.ht= ml#crashes-on-exit</a>. One fix, suggested by @ekhumoro on stackoverflow = (<a = href=3D"https://stackoverflow.com/questions/59120337/why-does-pyqt-sometim= es-crash-on-exit" target=3D"_blank" = class=3D"">https://stackoverflow.com/questions/59120337/why-does-pyqt-some= times-crash-on-exit</a>) was to delete the main window and the app = first, but that doesn't seem to fix it. I am running PyQt 5.12 because = that is the last version supported by conda, so I can't test the = one-exit fix in v5.13, and my users probably wouldn't have it installed = anyway. It happens on Macs and linux. <div class=3D""> </div> <div class=3D"">What I am asking is if there are additional things to = try in addition to @ekhumoro's suggestion? Basically he suggests doing = something like:</div> <div class=3D""> </div> <div class=3D""> <pre style=3D"margin-top:0px;margin-bottom:1em;padding:12px = 8px;border:0px;font-family:Consolas,Menlo,Monaco,"Lucida = Console","Liberation Mono","DejaVu Sans = Mono","Bitstream Vera Sans Mono","Courier = New",monospace,sans-serif;font-stretch:inherit;line-height:inherit;fo= nt-size:13px;vertical-align:baseline;box-sizing:inherit;width:auto;max-hei= ght:600px;overflow:auto;border-radius:3px;color:rgb(36,39,41)" = class=3D""><code = style=3D"margin:0px;padding:0px;border:0px;font-family:Consolas,Menlo,Mona= co,"Lucida Console","Liberation Mono","DejaVu = Sans Mono","Bitstream Vera Sans Mono","Courier = New",monospace,sans-serif;font-style:inherit;font-variant-caps:inheri= t;font-stretch:inherit;line-height:inherit;vertical-align:baseline;box-siz= ing:inherit;white-space:inherit" class=3D""><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">def</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> = main</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">():</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> app </span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">=3D</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> </span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit;color:rgb(43,145,175)" = class=3D"">QApplication</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">(</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">sys</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">.</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">argv</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">)</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> main_window </span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">=3D</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> </span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit;color:rgb(43,145,175)" = class=3D"">MainWindow</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">()</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> main_window</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">.</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">show</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">()</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> app</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">.</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">exec_</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">()</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> </span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""># ensure correct = deletion order</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> </span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">del</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> = main_window</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D"">,</span><span = style=3D"margin:0px;padding:0px;border:0px;font-family:inherit;font-style:= inherit;font-variant-caps:inherit;font-stretch:inherit;line-height:inherit= ;vertical-align:baseline;box-sizing:inherit" class=3D""> = app</span></code></pre> <div class=3D"">Does anyone understand why the crash only occurs if I = have calls to processEvents() in the code? It never happens when I = remove them.</div> </div> <div class=3D""> </div> <div class=3D"">Thanks,</div> <div class=3D"">Ray</div> <div class=3D""> </div> <div class=3D""> </div> </blockquote> </div> </div></blockquote></div><br class=3D""></div></div></blockquote></div><br= clear=3D"all" class=3D""><div class=3D""><br class=3D""></div>-- <br = class=3D""><div dir=3D"ltr" class=3D"gmail_signature">Thomas Caswell<br = class=3D""><a href=3D"mailto:[email protected]" target=3D"_blank" = class=3D"">[email protected]</a></div> </div></blockquote></div><br class=3D""></div></body></html>= --Apple-Mail=_86D63170-33FC-4FEE-A4B7-1F54C6016110--