Kara-Moon Forum

Developers & Technology => Musical MIDI Accompaniment (MMA) => Topic started by: sciurius on March 07, 2020, 08:03:17 PM



Title: Crash with plugins
Post by: sciurius on March 07, 2020, 08:03:17 PM
MMA 20.02, Fedora 31, Python 3.7.6.

Loading modules that use MMA/pluginsUtils.py may crash.

When the module calls setAuthor() or setDescription() and friends, pluginUtils.py calls (internally) _P().

_P() calls _getCallerFileName()

_getCallerFileName() processes all loaded modules, skipping modules that are None or do not have a __file__ attribute.

The __file__ attribute is then compared to the __file__ attribute of the calling module (the plugin). This crashes if the module has a __file__ attribute that is None.

Traceback (most recent call last):
  File "/home/jv/bin/mma", line 78, in <module>
    import MMA.main
  File "/home/jv/lib/mma/MMA/main.py", line 92, in <module>
    MMA.paths.readRC()
  File "/home/jv/lib/mma/MMA/paths.py", line 118, in readRC
    MMA.parse.parseFile(f)
  File "/home/jv/lib/mma/MMA/parse.py", line 91, in parseFile
    parse(f)
  File "/home/jv/lib/mma/MMA/parse.py", line 161, in parse
    simpleFuncs[action](l[1:])
  File "/home/jv/lib/mma/MMA/regplug.py", line 405, in plugin
    registerPlugin(p)
  File "/home/jv/lib/mma/MMA/regplug.py", line 295, in registerPlugin
    e = importlib.import_module(modName, package=None)
  File "/usr/lib64/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "/home/jv/lib/mma/plugins/customize/plugin.py", line 11, in <module>
    pu.setDescription("Customize MMA.")
  File "/home/jv/lib/mma/MMA/pluginUtils.py", line 103, in setDescription
    _P().DESCRIPTION = descr
  File "/home/jv/lib/mma/MMA/pluginUtils.py", line 94, in _P
    module = _getCallerModule()
  File "/home/jv/lib/mma/MMA/pluginUtils.py", line 81, in _getCallerModule
    if module.__file__.rpartition(".")[0] != f.rpartition(".")[0]:
AttributeError: 'NoneType' object has no attribute 'rpartition'

On my system this happens with the python module ruamel.yaml. It is in the list sys.modules with name 'ruamel', has a __file__ attribute, but its value is None.


Title: Re: Crash with plugins
Post by: bvdp on March 07, 2020, 09:10:36 PM
Neat. I've not done any MMA debugging for several weeks :) Oh, and in my defense on this one, I didn't write the code :)

But, could you post a short chuck of calling code for this please to save me writing it. I _think_ I see the problem, but I want to do it right.

Thanks so much for the report!


Title: Re: Crash with plugins
Post by: sciurius on March 07, 2020, 09:37:01 PM
This plugin should do:

https://github.com/sciurius/mma-plugins/tree/master/copyright

Crashing depends on whether you have modules without __file__. You can check with this small program:

Code:
import sys
for module in sys.modules.values():
    if module is None or not hasattr(module, "__file__"):
        continue
    if module.__file__ is None:
        print(module.__name__)



Title: Re: Crash with plugins
Post by: bvdp on March 08, 2020, 06:18:42 PM
I have traced it down to a problem with _getCallerModule() and offer this as an ugly replacement.

Code:
def _getCallerModule():
    f = _getCallerFileName()
    if f is None:
        return None
       
    for module in sys.modules.values():
        if module is None or not hasattr(module, "__file__"):
            continue
        try:
            if module.__file__.rpartition(".")[0] != f.rpartition(".")[0]:
                continue
        except:
            continue
        return module
   
    return None
   

And, no I don't think this is the real fix. Wrapping a bit of code with try/except is not good programming. But, for now I want to make sure that the bug is isolated. Please let me know.


Title: Re: Crash with plugins
Post by: bvdp on March 08, 2020, 06:35:23 PM
I meant to add that this bug is only present in Python3. Using Python2 avoids the program :)


Title: Re: Crash with plugins
Post by: sciurius on March 08, 2020, 07:28:53 PM
Modern Fedora has practically banned out python2, and with reason.

Anyway, why not try something simpler like:

    if module is None or not hasattr(module, "__file__") or module.__file__ is None:


Title: Re: Crash with plugins
Post by: bvdp on March 08, 2020, 09:21:36 PM
Thanks for the fix. I was going to do something like this later, but you beat me to it. Seems to work fine. So, here it is:

Code:
    
def _getCallerModule():
    f = _getCallerFileName()
    if f is None:
        return None
       
    for module in sys.modules.values():
        if module is None or not hasattr(module, "__file__") or module.__file__ is None:
            continue
        if module.__file__.rpartition(".")[0] != f.rpartition(".")[0]:
            continue
        return module
   
    return None

Guess the next developer version will be sooner than later :)



Title: Re: Crash with plugins
Post by: sciurius on March 10, 2020, 08:54:41 AM
Guess the next developer version will be sooner than later :)

I know I'm beating that dead horse again, but a github repo would make things easier...