diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py index 4a646c5e8f..823670b9cf 100644 --- a/openpype/hosts/fusion/api/menu.py +++ b/openpype/hosts/fusion/api/menu.py @@ -15,6 +15,8 @@ from openpype.hosts.fusion.api import ( set_framerange ) +from .pulse import FusionPulse + class Spacer(QtWidgets.QWidget): def __init__(self, height, *args, **kwargs): @@ -121,6 +123,10 @@ class OpenPypeMenu(QtWidgets.QWidget): self.register_callback("taskChanged", self.on_task_changed) self.on_task_changed() + # Force close current process if Fusion is closed + self._pulse = FusionPulse(parent=self) + self._pulse.start() + def on_task_changed(self): # Update current context label label = api.Session["AVALON_ASSET"] diff --git a/openpype/hosts/fusion/api/pulse.py b/openpype/hosts/fusion/api/pulse.py new file mode 100644 index 0000000000..cad1c74e13 --- /dev/null +++ b/openpype/hosts/fusion/api/pulse.py @@ -0,0 +1,62 @@ +import os +import sys + +from Qt import QtCore, QtWidgets + + +class PulseThread(QtCore.QThread): + no_response = QtCore.Signal() + + def __init__(self, parent=None): + super(PulseThread, self).__init__(parent=parent) + + # Interval in milliseconds + self._interval = os.environ.get("OPENPYPE_FUSION_PULSE_INTERVAL", 1000) + + def run(self): + app = getattr(sys.modules["__main__"], "app", None) + + while True: + if self.isInterruptionRequested(): + return + try: + app.Test() + except Exception: + self.no_response.emit() + + self.msleep(self._interval) + + +class FusionPulse(QtCore.QObject): + """A Timer that checks whether host app is still alive. + + This checks whether the Fusion process is still active at a certain + interval. This is useful due to how Fusion runs its scripts. Each script + runs in its own environment and process (a `fusionscript` process each). + If Fusion would go down and we have a UI process running at the same time + then it can happen that the `fusionscript.exe` will remain running in the + background in limbo due to e.g. a Qt interface's QApplication that keeps + running infinitely. + + Warning: + When the host is not detected this will automatically exit + the current process. + + """ + + def __init__(self, parent=None): + super(FusionPulse, self).__init__(parent=parent) + self._thread = PulseThread(parent=self) + self._thread.no_response.connect(self.on_no_response) + + def on_no_response(self): + print("Pulse detected no response from Fusion..") + sys.exit(1) + + def start(self): + self._thread.start() + + def stop(self): + self._thread.requestInterruption() + +