Colorbleed / maya-capture-gui

GUI front-end for maya-capture
MIT License
76 stars 29 forks source link

Maya fatal error when re-running the gui #46

Closed BigRoy closed 7 years ago

BigRoy commented 7 years ago

Problem

Maya sometimes crashes fatally when (re)running the gui.

To reproduce:

import capture_gui

app = capture_gui.main()
app.close()

Run this code, run it again, and again, and again. Most likely within the first 20 runs Maya would have already crashed. I'm unable to quickly identify the exact source of the problem, woohoo, time for some debugging?

aardschok commented 7 years ago

Opened the crash log and found this python stack


//Python stack:
  File: "<maya console>", line 11, in <module>()
  File: "C:\Users\User\Documents\development\maya-capture-gui\capture_gui\__init__.py", line 19, in main(show=True)
    parent = lib.get_maya_main_window()
  File: "C:\Users\User\Documents\development\maya-capture-gui\capture_gui\lib.py", line 367, in get_maya_main_window()
    for obj in QtWidgets.QApplication.topLevelWidgets():

Seems that we need to improve the get_maya_main_window() function

BigRoy commented 7 years ago

Interesting! @mottosso what do you think?

import capture_gui.lib
import capture_gui.app
from Qt import QtWidgets

def get_maya_main_window():
    """Return Maya's main window"""
    for obj in QtWidgets.QApplication.topLevelWidgets():
        if obj.objectName() == 'MayaWindow':
            return obj

parent = get_maya_main_window()

# launch app
window = capture_gui.app.App(title="Capture GUI",
                             parent=parent)
window.show()
window.close()

This crashes. Though this does not:


import capture_gui.lib
import capture_gui.app
from Qt import QtWidgets
import maya.OpenMayaUI as omui
try:
    import shiboken
except ImportError:
    import shiboken2 as shiboken

def get_maya_main_window():

   """

   Get the main Maya window as a QtGui.QMainWindow instance

   :return: QtGui.QMainWindow instance of the top level Maya windows

   """
   ptr = omui.MQtUtil.mainWindow()
   if ptr is not None:
       return shiboken.wrapInstance(long(ptr), QtWidgets.QWidget)

parent = get_maya_main_window()

# launch app
window = capture_gui.app.App(title="Capture GUI",
                             parent=parent)
window.show()
window.close()

Interestingly enough there seems to be some issues with the top level widgets. Probably a pointer that gets garbage collected too early?

More interestingly, running the first one in the same maya session after the second one makes it not crash. There's something in the second version that allows it to avoid the crash.

mottosso commented 7 years ago

Try replacing this:

QtWidgets.QApplication.topLevelWidgets()

With this:

QtWidgets.QApplication.instance().topLevelWidgets()
aardschok commented 7 years ago

Have replaced the line, new Maya and it is still crashing. Down below is a crash log from Maya.

MayaCrashLog17-05-10_10-29.txt

mottosso commented 7 years ago

How about this?

from Qt import QtWidgets

def get_maya_main_window():
    """Return Maya's main window"""
    app = QtWidgets.QApplication.instance()
    return {o.objectName(): o for o in app.topLevelWidgets()}["MayaWindow"]

parent = get_maya_main_window()

# launch app
window = capture_gui.app.App(title="Capture GUI",
                             parent=parent)
window.show()
window.close()
BigRoy commented 7 years ago

It seems to produce the same error. Though, interestingly enough, this works:

from Qt import QtWidgets
import capture_gui.app

widgets = QtWidgets.QApplication.instance().topLevelWidgets()
parent = {o.objectName(): o for o in widgets}["MayaWindow"]

# launch app
window = capture_gui.app.App(title="Capture GUI",
                             parent=parent)
window.show()
window.close()

And this does not:

from Qt import QtWidgets
import capture_gui.app

def get_maya_main_window():
    widgets = QtWidgets.QApplication.instance().topLevelWidgets()
    parent = {o.objectName(): o for o in widgets}["MayaWindow"]
    return parent

# launch app
window = capture_gui.app.App(title="Capture GUI",
                             parent=get_maya_main_window())
window.show()
window.close()

Note that when widgets isn't originally stored in the widgets variable it also crashes. (I'm testing this with Qt.py on PySide in Maya 2016 EXT1 SP6)

Whenever the app or widgets variable gets garbage collected things go haywire.

mottosso commented 7 years ago

I've encountered this before, where objects are garbage collected in the function, before being returned. This might be a bug in the binding.

BigRoy commented 7 years ago

Even though the problem is an interesting one because it was built in a way that we'd expected to just work I'm closing this issue. A fix was implemented in https://github.com/Colorbleed/maya-capture-gui/commit/86651c865b5e347aad4d56fdb6a493e268ebdc82 by swapping to using shiboken (or shiboken2).

Nevertheless, for sake of figuring out the original issue, feel free to continue discussion on this interesting bug.