diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj
index e2f7b0839..31e5c861b 100644
--- a/src/runtime/Python.Runtime.csproj
+++ b/src/runtime/Python.Runtime.csproj
@@ -1,8 +1,8 @@
-
+
Debug
- AnyCPU
+ x86
{097B4AC0-74E9-4C58-BCF8-C69746EC8271}
Library
Python.Runtime
@@ -22,35 +22,35 @@
-
+
- PYTHON2;PYTHON27;UCS4
+ MONO_OSX;PYTHON2;PYTHON27;UCS2
true
pdbonly
- PYTHON2;PYTHON27;UCS2
+
false
- PYTHON3;PYTHON36;UCS4
+ MONO_OSX;PYTHON3;PYTHON36;UCS4
true
pdbonly
false
true
- PYTHON2;PYTHON27;UCS4;TRACE;DEBUG
+ MONO_OSX;PYTHON2;PYTHON27;UCS2;TRACE;DEBUG
false
full
false
true
- PYTHON3;PYTHON36;UCS4;TRACE;DEBUG
+ MONO_OSX;PYTHON3;PYTHON36;UCS4;TRACE;DEBUG
false
full
false
@@ -171,8 +171,14 @@
$(TargetPath)
$(TargetDir)$(TargetName).pdb
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs
index b29eb72ca..28cb30a47 100644
--- a/src/runtime/runtime.cs
+++ b/src/runtime/runtime.cs
@@ -476,23 +476,6 @@ internal static void Shutdown()
Exceptions.Shutdown();
ImportHook.Shutdown();
Py_Finalize();
-
- // Now unload the Python library from memory and load it again, providing a
- // fresh interpreter. This prevents a crash (exception) on second domain reload
- // https://stackoverflow.com/questions/2445536/unload-a-dll-loaded-using-dllimport
- if (_PythonDll != "__Internal")
- {
- IntPtr dllLocal = NativeMethods.LoadLibrary(_PythonDll);
-
- // Twice: a first one for the call to LoadLibrary above,
- // a second one for the original call to LoadLibrary (should result in unloading the Python library from memory)
- NativeMethods.FreeLibrary(dllLocal);
- NativeMethods.FreeLibrary(dllLocal);
-
- // Here the Python library is supposed to be unloaded.
- // Load it again in order to get a fresh interpreter
- NativeMethods.LoadLibrary(_PythonDll);
- }
}
// called *without* the GIL acquired by clr._AtExit
diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs
index 6570ee083..4d7196ad5 100644
--- a/src/runtime/typemanager.cs
+++ b/src/runtime/typemanager.cs
@@ -454,7 +454,7 @@ internal static IntPtr AllocateTypeObject(string name)
///
internal static void InitializeSlots(IntPtr type, Type impl)
{
- var seen = new Hashtable(8);
+ var seen = new HashSet();
Type offsetType = typeof(TypeOffset);
while (impl != null)
@@ -473,7 +473,7 @@ internal static void InitializeSlots(IntPtr type, Type impl)
continue;
}
- if (seen[name] != null)
+ if (seen.Contains(name))
{
continue;
}
@@ -484,11 +484,40 @@ internal static void InitializeSlots(IntPtr type, Type impl)
IntPtr slot = Interop.GetThunk(method);
Marshal.WriteIntPtr(type, offset, slot);
- seen[name] = 1;
+ seen.Add(name);
}
impl = impl.BaseType;
}
+
+ // Hack: for some objects (Classbase and ExtensionType) we need gc
+ // support. We need to provide three functions:
+ // - tp_traverse(object, ...) returns 0
+ // - tp_clear(object) returns 0
+ // - tp_is_gc(type) returns non-zero
+ // In addition, these functions can get called after a domain reload,
+ // so they must be implemented in native code.
+ //
+ // Py_GetVersion reliably returns non-zero and uses no arguments.
+ //
+ // PyAST_Check reads the object and returns zero unless it's a
+ // python AST node. You could violate this assumption by making a C#
+ // type that derives from ast.AST -- but it's not clear why you'd do that.
+ if (seen.Contains("tp_traverse"))
+ {
+ var lib = NativeMethods.LoadLibrary(Runtime.PythonDLL);
+ var zeroslot = NativeMethods.GetProcAddress(lib, "PyAST_Check");
+ var trueslot = NativeMethods.GetProcAddress(lib, "Py_GetVersion");
+
+ var offset = (int)offsetType.GetField("tp_traverse").GetValue(offsetType);
+ Marshal.WriteIntPtr(type, offset, zeroslot);
+
+ offset = (int)offsetType.GetField("tp_clear").GetValue(offsetType);
+ Marshal.WriteIntPtr(type, offset, zeroslot);
+
+ offset = (int)offsetType.GetField("tp_is_gc").GetValue(offsetType);
+ Marshal.WriteIntPtr(type, offset, trueslot);
+ }
}