Conversation
|
In essence this would still be wrong - there's no need to store the The So wouldn't you only need to move the call to |
What I'm trying to fix here is the segfault that happens when using the the tools standalone, which I would imagine is the same issue as described in #514 |
What's the easiest way for me to reproduce this segfault on my end? Can I reproduce this in standalone Python? Any python Qt library should always cling on to the actual QApplication instance - it should somehow keep that reference unless maybe you'd reload the Qt libraries. :) I still feel, as I described there, that the actual segfault happens due to accessing the closed Qt widget with |
|
@tokejepsen does this behave the same? Run just in a Python command line interpreter. # assumes a running QApplication instance
from PyQt5 import QtWidgets, QtCore
app = QtWidgets.QApplication([])
window = QtWidgets.QDialog()
window.show()
app.exec_()
# this will crash, similar to what we're doing with `module.window`
window.show()
# note that this line below isn't even reached...
# because it crashes on the window.show()
# in this example both `app` and `window` variable persist
# but the crash is due to window having been destroyed...
app.exec_()
This seems like the problem you're running into instead. Maybe we should add on destroyed callback that removes itself from |
Tried with "your" code below and got the window to how twice but the python process is stuck. import sys
import contextlib
# assumes a running QApplication instance
from avalon.vendor.Qt import QtWidgets
@contextlib.contextmanager
def application():
app = QtWidgets.QApplication.instance()
if not app:
print("Starting new QApplication..")
app = QtWidgets.QApplication(sys.argv)
yield app
app.exec_()
else:
print("Using existing QApplication..")
yield app
with application():
app = QtWidgets.QApplication([])
window = QtWidgets.QDialog()
window.show()
app.exec_()
window.show()
# note that this line below isn't even reached...
# because it crashes on the window.show()
# in this example both `app` and `window` variable persist
# but the crash is due to window having been destroyed...
app.exec_()This is not what happens when I see the segfault. The python process crashes and exits.
I honestly dont know how and this is clearly going way over my head and comprehension. All I can say it that it makes the Photoshop integration which I'm working on, not error out, without affecting Nuke/Maya. Maybe the title is wrong and I shouldn't assume it'll fix #514. |
|
Funny that you say it now crashes on you too. I'm trying it again now... and it works fine. Ha, what is going on? It's as if the Window doesn't get destroyed/garbage collected in time one some occassions and it remains valid then? Anyway... can we add a comment above the line where store the QApplication into @jasperges could you see whether this fixes your issues too? Specifically #514 ? |
|
I have noticed just now that the This causes the |
avalon/tools/lib.py
Outdated
| self.app = QtWidgets.QApplication(sys.argv) | ||
| yield self.app | ||
|
|
||
| self.app.exec_() |
There was a problem hiding this comment.
@tokejepsen Please, don't always run self.app.exec_(). This screws up the Blender integration. I also think it's the responsibility of the creator of the QApplication to use exec_() if needed and shouldn't be called (again) for an existing QApplication instance.
If you could move it to the else block, I would be very happy. 🙂
There was a problem hiding this comment.
This is one of the issues that I'm seeing with the Photoshop integration. If we dont have that exec_() then I get an unresponsive window on the second launch.
Again not sure what the issue is with the unresponsive window.
What happens in Blender with always running exec_()?
There was a problem hiding this comment.
This is one of the issues that I'm seeing with the Photoshop integration. If we dont have that exec_() then I get an unresponsive window on the second launch.
Again not sure what the issue is with the unresponsive window.
The unresponsive window should be QApplication stopping with executing. This happens by default when the last Qt window closes as described at the top of this comment.
@jasperges would love to understand too why ._exec() would fail in Blender. From what I understood so far from Toke/David it will just return -1 in that case and disregard it.
There was a problem hiding this comment.
.exec_() doesn't fail, but it makes Blender unresponsive. After you quit all Qt Windows, Blenders GUI is responsive again.
Instead I use QApplication.processEvents() (which gets triggered every few milliseconds) to keep the Qt windows 'alive'.
There was a problem hiding this comment.
The problem that @jasperges describes should also be happening in C4D. In both those applications you should never trigger QApplication.exec_().
Should we maybe push those behind an environment variable for those applications that should never trigger it? AVALON_QTAPPLICATION_EXEC = False
Potentially adding it in the host's install() function?
There was a problem hiding this comment.
Should we maybe push those behind an environment variable for those applications that should never trigger it? AVALON_QTAPPLICATION_EXEC = False
Sounds good to me.
There was a problem hiding this comment.
Fine for me. One question though: why should the previous behaviour need to be changed at all?
If a new QApplication is spawned, run QApplication.exec_(). If an existing QApplication is already running, you might expect that it's event loop is also already running, right?
So apart from it causing issues with running Blender and Cinema4D (and possibly others), I don't understand why QApplication.exec_() should always be triggered.
There was a problem hiding this comment.
@BigRoy I guess so, I will have to check with @kguyaux and his TVPaint integration. |
|
Have put the execution of existing QApplications behind the environment variable |
|
I think the change made in this commit with the environment variable actually also would be intended for the first start of the QApplication. If I'm not mistaken, then for Blender and Cinema4D you should never call Previously I worked around it by creating an Instance before calling any of the Avalon tools as that would mean it would always skip trying to call Other than that, I can live with this PR. It's one of those oddities I don't really understand but it seems to fix things for your use case so I guess it's a required change. |
Hmm, I think I should maybe follow your example and just enforce the QApplication for the Photoshop integration only. This PR does not have enough grounding, and it affects too much code to just add. Closing this and fixing in #524 |
What's changed?
Store QApplication at module level and always exec.
Spawned from #520
This has been tested standalone and in Maya/Nuke.