Skip to content

Crash when using nested classes with inheritance, which are instantiated from C# #1414

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
koliyo opened this issue Mar 10, 2021 · 3 comments
Closed
Assignees
Labels
Milestone

Comments

@koliyo
Copy link

koliyo commented Mar 10, 2021

Environment

  • Pythonnet version: 2.5.1
  • Python version: Python 3.9.2
  • Operating System: MacOS
  • .NET Runtime: 5.0.200

Details

  • Describe what you were trying to get done.

I am accessing a member of a nested C# class which inherits from the enclosing class.

When doing this, the Pythonnet runtime crashes!

Here is a minimal example:

namespace pythonnet_testing {

  public class Bar {
    public class Hej : Bar {
    }
  }

  public class Foo {
    public Bar Bar;

    public static Foo Create() {
      Foo f = new();
      f.Bar = new Bar.Hej();
      return f;
    }
  }

  class Program {
    static void Main(string[] args) {

      var pyCode = @"
import pythonnet_testing
f = pythonnet_testing.Foo.Create()
print('Trying to access member of nested subclass')
print(f'Bar: {f.Bar}')
      ";

      PythonEngine.Initialize();

      using (Py.GIL()) {
        PythonEngine.Exec(pyCode);
      }

      Console.WriteLine("EXIT");
    }
  }
}

This seem to be specifically for nested classes, where the object instance is created from the C# environment, and the class has not been explicitly referenced/used from python.

I have found a way to prevent the crash, by first explicitly using the nested class in the python code.

Eg instead of this:

import pythonnet_testing
f = pythonnet_testing.Foo.Create()
print('Trying to access member of nested subclass')
print(f'Bar: {f.Bar}')

I insert a reference to the nested Bar.Hej class

import pythonnet_testing
f = pythonnet_testing.Foo.Create()
print('Trying to access member of nested subclass')
_ = pythonnet_testing.Bar.Hej # Explicitly referencing the nested class
print(f'Bar: {f.Bar}')

If I do this, then the Pythonnet runtime no longer crashes. It is even enough to reference the enclosing baseclass Bar

_ = pythonnet_testing.Bar # Explicitly referencing the enclosing class
print(f'Bar: {f.Bar}')

When I do this, the python code executes properly:

Trying to access member of nested subclass
Bar: pythonnet_testing.Bar+Hej
@filmor
Copy link
Member

filmor commented Mar 10, 2021

Thank you for the bug report. Two things:

  1. What does the actual stacktrace or error message look like when it's crashing?
  2. Could you check whether the problem exists on master as well?

@koliyo
Copy link
Author

koliyo commented Mar 10, 2021

On my Mac I do not get any error message, the process dies silently. I have a report from a Windows machine with the following error:

Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:
                                                                                                                                                                   --------------------------------
at Python.Runtime.Runtime.PyDict_SetItemString(IntPtr, System.String, IntPtr)
                                      --------------------------------
at Python.Runtime.ClassManager.InitClassBase(System.Type, Python.Runtime.ClassBase)
at Python.Runtime.ClassManager.GetClass(System.Type)
at Python.Runtime.TypeManager.CreateType(Python.Runtime.ManagedType, System.Type)
at Python.Runtime.TypeManager.GetTypeHandle(Python.Runtime.ManagedType, System.Type)
at Python.Runtime.ClassManager.InitClassBase(System.Type, Python.Runtime.ClassBase)
at Python.Runtime.ClassManager.GetClass(System.Type)
at Python.Runtime.Converter.ToPython(System.Object, System.Type)
at Python.Runtime.Converter.ToPython(System.Object, System.Type)
at Python.Runtime.MethodBinder.Invoke(IntPtr, IntPtr, IntPtr, System.Reflection.MethodBase, System.Reflection.MethodInfo[])
at Python.Runtime.MethodBinder.Invoke(IntPtr, IntPtr, IntPtr)
at Python.Runtime.Indexer.GetItem(IntPtr, IntPtr)
at Python.Runtime.ClassObject.mp_subscript(IntPtr, IntPtr)

I have also tested this in master, and the same crash and workaround applies.

@filmor
Copy link
Member

filmor commented Mar 10, 2021

Thank you, I'll try to reproduce this.

@filmor filmor self-assigned this Mar 10, 2021
@filmor filmor added the bug label Mar 10, 2021
@filmor filmor added this to the 3.0.0 milestone Mar 10, 2021
lostmsu added a commit to losttech/pythonnet that referenced this issue Oct 1, 2021
…located.

fixes pythonnet#1414

Without this fix attempting to use a nested .NET class that derives from its parent would cause a crash due to false mutual dependency.
@lostmsu lostmsu closed this as completed in f857d59 Oct 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants