<div dir="ltr"><div class="gmail_default" style="font-family:courier new,monospace"><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">Hello!</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">We have a C++/Qt application that provides both a C++ api and a SIP wrapped Python api.  When converting everything from Python 2.7 to Python 3, we began to see crashes when python applications using our api exited/quit.  I have been tracking this crash down, and I think I have a decent understanding of what's causing it, which I'll attempt to explain below.  However, I don't feel like I have a good understanding of why the code path that leads to the crash does what it does.  In other words, I'm not sure if it's expected behavior, or a bug.  That's what I'm hoping you might be able to assist with.</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">I have a simple-ish reproducer:</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"><a href="https://github.com/kevinconstantine/pyqt-crash" target="_blank">https://github.com/kevinconstantine/pyqt-crash</a></span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">that demonstrates the problem if needed. If it's a bug, I have a patch that prevents the crash, but given my current understanding of what's going on, it may not be the right direction.</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">Versions</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">Python: 3.7.7</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">Qt: 5.15.2</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">PyQt: 5.15.4 (problem likely exists in 6.4.0 as well given code similarities)</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">sip: 4.19.30</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">Summary</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">It looks like in Python3, PyQt has registered a call-back when the application exits</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> </span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">(</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">cleanup_on_exit()</span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">)</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">.  </span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">The call chain eventually results in</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> sip_api_visit_wrapper() </span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">looping over SIP objects and calling PyQt's</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> cleanup_qobject().  cleanup_qobject() </span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">checks if the object is owned by Python and checks if the object is a QObject.  If the object is owned by C++ or not a QObject, it returns early.  Once we've established that the object is owned by Python, it looks like it transfers ownership of the Python sipWrapper object to C++, and then calls delete on the address of the sipWrapper object.</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">This delete causes the C++ destructors to get called, however, the SIP destructor is never called.  I would expect that a python owned object would have that SIP destructor called.  We are relying on doing some cleanup inside of the SIP destructor, and because that doesn't get executed, the application crashes.</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">More detail on what we're doing</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">For years, we've leveraged a couple of examples (</span><a href="https://riverbankcomputing.com/pipermail/pyqt/2005-March/010031.html" target="_blank" style="text-decoration:none"><span style="font-size:11pt;font-family:Arial;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">here</span></a><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">, and </span><a href="https://www.riverbankcomputing.com/pipermail/pyqt/2017-September/039548.html" target="_blank" style="text-decoration:none"><span style="font-size:11pt;font-family:Arial;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">here</span></a><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">) to handle tracking shared pointers on the C++ side of things as they got created through Python.  We have a hand-coded SIP destructor that gets called from Python that removes the shared pointer from a map so that it too gets destructed properly.  This all worked great until we tried to migrate to Python 3 (cue the ominous music).</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">What's happening (at least my understanding of what's happening)</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">In Python3, PyQt has registered</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> cleanup_on_exit() </span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">with </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">sipRegisterExitNotifier() </span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">in </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">qpy/QtCore/qpycore_init.cpp.</span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">  So when the application is exiting, </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">cleanup_on_exit()</span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> is called and the call-stack looks like:</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">PyQt: cleanup_on_exit()</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">  PyQt: pyqt5_cleanup_qobjects()</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">    SIP: sip_api_visit_wrappers() // Loop over sip objects</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">      PyQt: cleanup_qobject()</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">Within </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">qpy/QtCore/qpycore_public_api.cpp:cleanup_qobject()</span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">, several checks are made that cause the function to return early without doing anything:</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">1. Anything not owned by Python returns early</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">2. Non QObjects return early</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">3. Running threads return early</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">But if an object passes all of these checks, the code </span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">calls </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">sipTransferTo()</span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> to transfer ownership of the sipWrapper object to C++</span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">, and then calls delete on the address of the sipWrapper object.</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">This delete causes the C++ destructors to get called, but most importantly, the SIP destructor that we're relying on, is never called.  As mentioned earlier, we are relying on the SIP destructor to clean up the global shared_ptr storage when the Python object is destroyed.  My expectation is  that a Python owned object would have that SIP destructor called just like the SIP constructor is called when the object is created.  </span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">I added debugging output to SIP, PyQt, and my codebase in an effort to understand what was happening.  I'm hesitant to include that in this initial email as it gets kind of dense trying to explain what's going on, but I'm happy to provide it if I can interest anyone in going down the rabbit hole with me on this one.  </span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">I also have a small patch that "fixes" my crash, but I'm not sure that I completely have the right understanding of all of these pieces and that this doesn’t cause an issue elsewhere.</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">  </span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">--- PyQt5-5.15.4.vanilla/qpy/QtCore/qpycore_public_api.cpp 2021-03-05 01:57:14.957003000 -0800</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">+++ PyQt5-5.15.4.kcc/qpy/QtCore/qpycore_public_api.cpp 2022-12-15 08:40:06.644173000 -0800</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">@@ -60,6 +60,13 @@</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">             return;</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">     }</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> </span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">+    // Try to destroy the object if it still has a reference</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">+    // Goal is to get the SIP dtor to fire.</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">+    if (Py_REFCNT((PyObject *)sw)) {</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">+        sipInstanceDestroyed(sw);</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">+        return;</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">+    }</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">+</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">     sipTransferTo((PyObject *)sw, SIP_NULLPTR);</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> </span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">     Py_BEGIN_ALLOW_THREADS</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">By calling </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">sipInstanceDestroyed()</span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">, the SIP destructor fires, and subsequently the C++ dtors get executed as well.  Everything appears to get cleaned up in the proper order, and we avoid the crash.  I have not reproduced the issue in PyQt6, but there are no differences in</span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> cleanup_qobject() </span><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">between the two versions, so I'm assuming the behavior is similar.</span></p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="color:rgb(0,0,0);line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">Thanks so much for any help you can provide in fixing this, or helping me understand better what's going on. </span><span style="font-size:11pt;font-family:"Courier New";color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap"> </span></p><font color="#888888"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"> </p><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style="font-size:11pt;font-family:Arial;color:rgb(34,34,34);font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;vertical-align:baseline;white-space:pre-wrap">-kevin</span></p></font></div></div>