Skip to content

Commit aa63f0b

Browse files
committed
* Stash for ImportHook
* Refactor Save/Load * Fix refcnt error for moduleobject.cs
1 parent 39f47c8 commit aa63f0b

12 files changed

Lines changed: 102 additions & 42 deletions

src/embed_tests/TestDomainReload.cs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -233,26 +233,33 @@ public static void RunPython()
233233
mode = ShutdownMode.Soft;
234234
}
235235
PythonEngine.Initialize(mode: mode);
236-
using (Py.GIL())
236+
try
237237
{
238-
try
239-
{
240-
var pyScript = string.Format("import clr\n"
241-
+ "print('[{0} in python] imported clr')\n"
242-
+ "clr.AddReference('System')\n"
243-
+ "print('[{0} in python] allocated a clr object')\n"
244-
+ "import gc\n"
245-
+ "gc.collect()\n"
246-
+ "print('[{0} in python] collected garbage')\n",
247-
name);
248-
PythonEngine.Exec(pyScript);
249-
}
250-
catch (Exception e)
238+
using (Py.GIL())
251239
{
252-
Console.WriteLine(string.Format("[{0} in .NET] Caught exception: {1}", name, e));
240+
try
241+
{
242+
var pyScript = string.Format("import clr\n"
243+
+ "print('[{0} in python] imported clr')\n"
244+
+ "clr.AddReference('System')\n"
245+
+ "print('[{0} in python] allocated a clr object')\n"
246+
+ "import gc\n"
247+
+ "gc.collect()\n"
248+
+ "print('[{0} in python] collected garbage')\n",
249+
name);
250+
PythonEngine.Exec(pyScript);
251+
}
252+
catch (Exception e)
253+
{
254+
Console.WriteLine(string.Format("[{0} in .NET] Caught exception: {1}", name, e));
255+
throw;
256+
}
253257
}
254258
}
255-
PythonEngine.BeginAllowThreads();
259+
finally
260+
{
261+
PythonEngine.BeginAllowThreads();
262+
}
256263
}
257264

258265

src/runtime/classbase.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,5 +303,12 @@ public static int tp_clear(IntPtr ob)
303303
self.tpHandle = IntPtr.Zero;
304304
return 0;
305305
}
306+
307+
protected override void OnLoad()
308+
{
309+
base.OnLoad();
310+
gcHandle = AllocGCHandle();
311+
Marshal.WriteIntPtr(pyHandle, TypeOffset.magic(), (IntPtr)gcHandle);
312+
}
306313
}
307314
}

src/runtime/classmanager.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ internal static void RemoveClasses()
5656
cls.CallTypeTraverse(OnVisit, visitedPtr);
5757
// XXX: Force release instance resources but not dealloc itself.
5858
cls.CallTypeClear();
59+
cls.DecrRefCount();
5960
}
6061
}
6162
finally
6263
{
6364
visitedHandle.Free();
6465
}
66+
cache.Clear();
6567
}
6668

6769
private static int OnVisit(IntPtr ob, IntPtr arg)
@@ -81,15 +83,25 @@ private static int OnVisit(IntPtr ob, IntPtr arg)
8183
return 0;
8284
}
8385

84-
8586
internal static void StashPush(RuntimeDataStorage storage)
8687
{
8788
storage.PushValue(cache);
89+
foreach (var cls in cache.Values)
90+
{
91+
// This incref is for cache to hold the cls,
92+
// thus no need for decreasing it at StashPop.
93+
Runtime.XIncref(cls.pyHandle);
94+
cls.Save();
95+
}
8896
}
8997

9098
internal static void StashPop(RuntimeDataStorage storage)
9199
{
92100
cache = storage.PopValue<Dictionary<Type, ClassBase>>();
101+
foreach (var cls in cache.Values)
102+
{
103+
cls.Load();
104+
}
93105
}
94106

95107
/// <summary>

src/runtime/eventbinding.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,5 @@ public static int tp_clear(IntPtr ob)
128128
Runtime.Py_CLEAR(ref self.target);
129129
return 0;
130130
}
131-
132-
protected override void OnSave()
133-
{
134-
base.OnSave();
135-
Runtime.XIncref(target);
136-
}
137131
}
138132
}

src/runtime/exceptions.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,11 @@ internal static Exception ToException(IntPtr ob)
8989
/// <remarks>
9090
/// Readability of the Exceptions class improvements as we look toward version 2.7 ...
9191
/// </remarks>
92-
public class Exceptions
92+
public static class Exceptions
9393
{
9494
internal static IntPtr warnings_module;
9595
internal static IntPtr exceptions_module;
9696

97-
private Exceptions()
98-
{
99-
}
100-
10197
/// <summary>
10298
/// Initialization performed on startup of the Python runtime.
10399
/// </summary>

src/runtime/extensiontype.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,6 @@ public static void tp_dealloc(IntPtr ob)
9898
self.Dealloc();
9999
}
100100

101-
protected override void OnSave()
102-
{
103-
base.OnSave();
104-
Runtime.XIncref(pyHandle);
105-
}
106-
107101
protected override void OnLoad()
108102
{
109103
base.OnLoad();

src/runtime/importhook.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Python.Runtime
66
/// <summary>
77
/// Implements the "import hook" used to integrate Python with the CLR.
88
/// </summary>
9-
internal class ImportHook
9+
internal static class ImportHook
1010
{
1111
private static IntPtr py_import;
1212
private static CLRModule root;
@@ -130,6 +130,22 @@ internal static void Shutdown()
130130
CLRModule.Reset();
131131
}
132132

133+
internal static void StashPush(RuntimeDataStorage storage)
134+
{
135+
Runtime.XIncref(py_clr_module);
136+
Runtime.XIncref(root.pyHandle);
137+
storage.AddValue("py_clr_module", py_clr_module);
138+
storage.AddValue("root", root.pyHandle);
139+
}
140+
141+
internal static void StashPop(RuntimeDataStorage storage)
142+
{
143+
InitImport();
144+
storage.GetValue("py_clr_module", out py_clr_module);
145+
var rootHandle = storage.GetValue<IntPtr>("root");
146+
root = (CLRModule)ManagedType.GetManagedObject(rootHandle);
147+
}
148+
133149
/// <summary>
134150
/// Return the clr python module (new reference)
135151
/// </summary>

src/runtime/managedtype.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,14 @@ protected void TypeClear()
202202

203203
internal void Save()
204204
{
205+
Runtime.XIncref(pyHandle);
205206
OnSave();
206207
}
207208

208209
internal void Load()
209210
{
210211
OnLoad();
212+
Runtime.XDecref(pyHandle);
211213
}
212214

213215
protected virtual void OnSave() { }

src/runtime/moduleobject.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public ManagedType GetAttribute(string name, bool guess)
103103
{
104104
m = new ModuleObject(qname);
105105
StoreAttribute(name, m);
106+
m.DecrRefCount();
106107
return m;
107108
}
108109

@@ -118,6 +119,7 @@ public ManagedType GetAttribute(string name, bool guess)
118119
}
119120
c = ClassManager.GetClass(type);
120121
StoreAttribute(name, c);
122+
c.DecrRefCount();
121123
return c;
122124
}
123125

@@ -132,6 +134,7 @@ public ManagedType GetAttribute(string name, bool guess)
132134
{
133135
m = new ModuleObject(qname);
134136
StoreAttribute(name, m);
137+
m.DecrRefCount();
135138
return m;
136139
}
137140

@@ -144,6 +147,7 @@ public ManagedType GetAttribute(string name, bool guess)
144147
}
145148
c = ClassManager.GetClass(type);
146149
StoreAttribute(name, c);
150+
c.DecrRefCount();
147151
return c;
148152
}
149153
}
@@ -239,6 +243,7 @@ internal void InitializeModuleMembers()
239243
mi[0] = method;
240244
var m = new ModuleFunctionObject(type, name, mi, allow_threads);
241245
StoreAttribute(name, m);
246+
m.DecrRefCount();
242247
}
243248
}
244249

@@ -251,6 +256,7 @@ internal void InitializeModuleMembers()
251256
string name = property.Name;
252257
var p = new ModulePropertyObject(property);
253258
StoreAttribute(name, p);
259+
p.DecrRefCount();
254260
}
255261
}
256262
type = type.BaseType;

src/runtime/runtime.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,9 +197,9 @@ internal static void Initialize(bool initSigs = false, ShutdownMode mode = Shutd
197197
#endif
198198
{
199199
PyCLRMetaType = MetaType.Initialize(); // Steal a reference
200+
ImportHook.Initialize();
200201
}
201202
Exceptions.Initialize();
202-
ImportHook.Initialize();
203203

204204
// Need to add the runtime directory to sys.path so that we
205205
// can find built-in assemblies like System.Data, et. al.
@@ -497,13 +497,16 @@ private static void MoveClrInstancesOnwershipToPython()
497497
obj.CallTypeClear();
498498
// obj's tp_type will degenerate to a pure Python type after TypeManager.RemoveTypes(),
499499
// thus just be safe to give it back to GC chain.
500-
PyObject_GC_Track(obj.pyHandle);
500+
if (!_PyObject_GC_IS_TRACKED(obj.pyHandle))
501+
{
502+
PyObject_GC_Track(obj.pyHandle);
503+
}
501504
}
502505
if (obj.gcHandle.IsAllocated)
503506
{
504507
obj.gcHandle.Free();
505508
}
506-
obj.gcHandle = new GCHandle();
509+
obj.gcHandle = default;
507510
}
508511
ManagedType.ClearTrackedObjects();
509512
}

0 commit comments

Comments
 (0)