From 38654719530cef3f53729a7488a4467b1f540656 Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Thu, 25 Aug 2016 16:27:28 +0200 Subject: [PATCH 1/2] add test that reproduces the stackoverflowexception. --- src/testing/subclasstest.cs | 11 +++++++++++ src/tests/test_suite/__init__.py | 2 ++ src/tests/test_suite/test_recursiveTypes.py | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/tests/test_suite/test_recursiveTypes.py diff --git a/src/testing/subclasstest.cs b/src/testing/subclasstest.cs index 5d8f171c8..4fd271fa7 100644 --- a/src/testing/subclasstest.cs +++ b/src/testing/subclasstest.cs @@ -64,6 +64,17 @@ public virtual void OnTestEvent(int value) } } + public abstract class RecursiveInheritance + { + public class SubClass : RecursiveInheritance + { + public void SomeMethod() + { + + } + } + } + public class TestFunctions { public static string test_foo(IInterfaceTest x) diff --git a/src/tests/test_suite/__init__.py b/src/tests/test_suite/__init__.py index 1ca730d7b..5b1cc4ae4 100644 --- a/src/tests/test_suite/__init__.py +++ b/src/tests/test_suite/__init__.py @@ -4,9 +4,11 @@ from .test_import import test_suite as import_tests from .test_callback import test_suite as callback_tests +from .test_recursiveTypes import test_suite as recursiveTypes_tests def test_suite(): suite = unittest.TestSuite() suite.addTests((import_tests(),)) suite.addTests((callback_tests(),)) + suite.addTests((recursiveTypes_tests(),)) return suite \ No newline at end of file diff --git a/src/tests/test_suite/test_recursiveTypes.py b/src/tests/test_suite/test_recursiveTypes.py new file mode 100644 index 000000000..290d7236a --- /dev/null +++ b/src/tests/test_suite/test_recursiveTypes.py @@ -0,0 +1,20 @@ +import unittest, sys +import clr + +this_module = sys.modules[__name__] +clr.AddReference("Python.Test") +class RecursiveTypesTests(unittest.TestCase): + """Test if interop with recursive type inheritance works.""" + + def testRecursiveTypeCreation(self): + """Test that a recursive types don't crash with a StackOverflowException""" + import Python.Test as Test + from Python.Test import RecursiveInheritance + test_instance = RecursiveInheritance.SubClass() + test_instance.SomeMethod() + pass + + +def test_suite(): + return unittest.makeSuite(RecursiveTypesTests) + From 502001e6db4f0d7f198d677ec4e1e165054a37fd Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Fri, 26 Aug 2016 15:07:12 +0200 Subject: [PATCH 2/2] fix stackoverflowexception --- src/runtime/classmanager.cs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/runtime/classmanager.cs b/src/runtime/classmanager.cs index 6c6aa3b09..d85dd2daa 100644 --- a/src/runtime/classmanager.cs +++ b/src/runtime/classmanager.cs @@ -50,6 +50,8 @@ internal static ClassBase GetClass(Type type) } cb = CreateClass(type); cache.Add(type, cb); + // Initialize the object later, as this might call this GetClass method recursivly (for example when a nested class inherits its declaring class...) + InitClassBase(type, cb); return cb; } @@ -62,12 +64,6 @@ internal static ClassBase GetClass(Type type) private static ClassBase CreateClass(Type type) { - // First, we introspect the managed type and build some class - // information, including generating the member descriptors - // that we'll be putting in the Python class __dict__. - - ClassInfo info = GetClassInfo(type); - // Next, select the appropriate managed implementation class. // Different kinds of types, such as array types or interface // types, want to vary certain implementation details to make @@ -115,6 +111,18 @@ private static ClassBase CreateClass(Type type) impl = new ClassObject(type); } + + return impl; + } + + private static void InitClassBase(Type type, ClassBase impl) + { + // First, we introspect the managed type and build some class + // information, including generating the member descriptors + // that we'll be putting in the Python class __dict__. + + ClassInfo info = GetClassInfo(type); + impl.indexer = info.indexer; // Now we allocate the Python type object to reflect the given @@ -182,10 +190,8 @@ private static ClassBase CreateClass(Type type) } } - return impl; } - private static ClassInfo GetClassInfo(Type type) { ClassInfo ci = new ClassInfo(type); @@ -353,6 +359,7 @@ private static ClassInfo GetClassInfo(Type type) if (!(tp.IsNestedPublic || tp.IsNestedFamily || tp.IsNestedFamORAssem)) continue; + // Note the given instance might be uninitialized ob = ClassManager.GetClass(tp); ci.members[mi.Name] = ob; continue;