On 30/11/2022 3:06 am, Bob Kline wrote:
Cranking up the microscope (or spelunking deeper, whichever metaphor
you prefer), the first thing I'll say is that this code is devilishly
complex.

Here's what I've found in the latest pass.

First, there's a minor bug at line 353 of pyscript.py [1], where
globalNameSpaceModule is set to None when it's
self.globalNameSpaceModule which should be set to None. The bug is
currently innocuous, as the only invocation of the method in which
that assignment is made in this version of the code is from
PyScript.Close(), and that method makes the correct assignment:

Oops, yeah, that looks like a bug (but note that the links you are using are from sublime text, not from pywin32 - it looks quite old - the correct link is https://github.com/mhammond/pywin32/blob/main/com/win32comext/axscript/client/pyscript.py where it is at line 416.

     self.globalNameSpaceModule = None

It seems to me that there's a more serious problem at line 350 of that
module [2], where that same method appears to be invoking a method
which does not exist, at least as far as I can determine (bearing in
mind that I might not completely understand all the nuances of the
tricky code here).

     self.globalNameSpaceModule.ax._Reset_()

Working backward, to see if I can figure out where _Reset_ would be
defined, I found this code in the PyScript class:

     def InitNew(self):
         framework.COMScript.InitNew(self)
         import imp
         self.scriptDispatch = None
         self.globalNameSpaceModule = imp.new_module("__ax_main__")
         self.globalNameSpaceModule.__dict__['ax'] = AXScriptAttribute(self)
         ....

It's not completely clear how this method gets invoked (I don't see
any calls to it, but I do see that "InitNew" appears as one of the
strings in the _public_methods_ array attribute of the base class),

Yes, that's a COM method, so called by the host - see https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.debugger.interop.iactivescriptparse64. That try/except block was probably just handling the case where Reset is called twice without an InitNew call in between (in which case self.globalNameSpaceModule is None, so will not have a .ax attribute) - but I agree with your analysis that even if it *did* have that attribute, the ax object isn't going to have a Reset - so whatever that's trying to do isn't getting done.

As a side note, imp.new_module() [3] was deprecated back in Python 3.4.

Yep, you are looking at a very old version.

I'm attaching the logs I captured. One set is for a session in which
the macro was only invoked once (and therefore didn't result in any
observable failures) and the other for the session in which the macro
was invoked twice, with the symptoms described earlier in this thread.
Please let me know if anything else stands out as potentially useful

Nothing stands out there :( But that's not particularly surprising as it really should be impossible for bugs in that .py code to crash the process - strangeness could happen, but an access violation shouldn't be possible. Something like a COM reference counting bug in (either in axscript or in the host) could explain this.

Re your other message, when I say I'm hoping to see a stack trace, I mean a native stack trace, as should be shown in the event viewer or in a JIT debugger, which will show the symbols in the various DLLs rather than the Python functions. Eg, it showing the crash happening in, say, IUnknown::Release would imply such a reference counting bug, or if it instead shows it in some other COM method it would help narrow down the problem area. Unfortunately, without knowing your environment I can't offer specific advice about how to get it - but running the crashing program under any Visual Studio version would certainly offer it.

HTH,

Mark

_______________________________________________
python-win32 mailing list
python-win32@python.org
https://mail.python.org/mailman/listinfo/python-win32

Reply via email to