Skip to content

Commit 6ebf485

Browse files
amos402filmor
authored andcommitted
Fix Shutdown crash
1 parent 3673526 commit 6ebf485

File tree

7 files changed

+47
-15
lines changed

7 files changed

+47
-15
lines changed

src/runtime/classbase.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,10 @@ public static IntPtr tp_repr(IntPtr ob)
354354
public static void tp_dealloc(IntPtr ob)
355355
{
356356
ManagedType self = GetManagedObject(ob);
357-
tp_clear(ob);
358-
Runtime.PyObject_GC_UnTrack(self.pyHandle);
359-
Runtime.PyObject_GC_Del(self.pyHandle);
357+
RemoveObjectDict(ob);
358+
Runtime.Py_CLEAR(ref self.tpHandle);
359+
Runtime.PyObject_GC_UnTrack(ob);
360+
Runtime.PyObject_GC_Del(ob);
360361
self.FreeGCHandle();
361362
}
362363

src/runtime/classmanager.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Runtime.InteropServices;
66
using System.Security;
77
using System.Linq;
8+
using System.Diagnostics;
89

910
namespace Python.Runtime
1011
{
@@ -270,7 +271,7 @@ private static void InitClassBase(Type type, ClassBase impl)
270271

271272
// Finally, initialize the class __dict__ and return the object.
272273
var dict = new BorrowedReference(Marshal.ReadIntPtr(tp, TypeOffset.tp_dict));
273-
274+
Debug.Assert(!dict.IsNull);
274275

275276
if (impl.dotNetMembers == null)
276277
{

src/runtime/extensiontype.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void SetupGc ()
5555
/// </summary>
5656
public static void FinalizeObject(ManagedType self)
5757
{
58-
ClearObjectDict(self.pyHandle);
58+
RemoveObjectDict(self.pyHandle);
5959
Runtime.PyObject_GC_Del(self.pyHandle);
6060
// Not necessary for decref of `tpHandle`.
6161
self.FreeGCHandle();

src/runtime/managedtype.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,16 @@ protected virtual void OnSave(InterDomainContext context) { }
243243
protected virtual void OnLoad(InterDomainContext context) { }
244244

245245
protected static void ClearObjectDict(IntPtr ob)
246+
{
247+
IntPtr dict = GetObjectDict(ob);
248+
if (dict == IntPtr.Zero)
249+
{
250+
return;
251+
}
252+
Runtime.PyDict_Clear(dict);
253+
}
254+
255+
protected static void RemoveObjectDict(IntPtr ob)
246256
{
247257
IntPtr dict = GetObjectDict(ob);
248258
if (dict == IntPtr.Zero)

src/runtime/metatype.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,12 @@ public static void tp_dealloc(IntPtr tp)
304304
NativeCall.Void_Call_1(op, tp);
305305
}
306306

307+
public static int tp_clear(IntPtr ob)
308+
{
309+
ClearObjectDict(ob);
310+
return 0;
311+
}
312+
307313
private static IntPtr DoInstanceCheck(IntPtr tp, IntPtr args, bool checkType)
308314
{
309315
var cb = GetManagedObject(tp) as ClassBase;

src/runtime/methodobject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ public static IntPtr tp_repr(IntPtr ob)
217217
{
218218
var self = (MethodObject)GetManagedObject(ob);
219219
self.ClearMembers();
220-
ClearObjectDict(ob);
220+
RemoveObjectDict(ob);
221221
self.Dealloc();
222222
}
223223

src/runtime/runtime.cs

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -503,15 +503,19 @@ private static void PyDictTryDelItem(BorrowedReference dict, string key)
503503
private static void MoveClrInstancesOnwershipToPython()
504504
{
505505
var objs = ManagedType.GetManagedObjects();
506-
var copyObjs = objs.ToArray();
507-
foreach (var entry in copyObjs)
506+
var copyObjs = new KeyValuePair<ManagedType, ManagedType.TrackTypes>[objs.Count];
508507
{
509-
ManagedType obj = entry.Key;
510-
if (!objs.ContainsKey(obj))
508+
int i = 0;
509+
foreach (var entry in objs)
511510
{
512-
System.Diagnostics.Debug.Assert(obj.gcHandle == default);
513-
continue;
511+
ManagedType obj = entry.Key;
512+
XIncref(obj.pyHandle);
513+
copyObjs[i++] = entry;
514514
}
515+
}
516+
foreach (var entry in copyObjs)
517+
{
518+
ManagedType obj = entry.Key;
515519
if (entry.Value == ManagedType.TrackTypes.Extension)
516520
{
517521
obj.CallTypeClear();
@@ -522,11 +526,21 @@ private static void MoveClrInstancesOnwershipToPython()
522526
PyObject_GC_Track(obj.pyHandle);
523527
}
524528
}
525-
if (obj.gcHandle.IsAllocated)
529+
}
530+
foreach (var entry in copyObjs)
531+
{
532+
ManagedType obj = entry.Key;
533+
if (!objs.ContainsKey(obj))
534+
{
535+
System.Diagnostics.Debug.Assert(obj.gcHandle == default);
536+
continue;
537+
}
538+
if (obj.RefCount > 1)
526539
{
527-
obj.gcHandle.Free();
540+
obj.FreeGCHandle();
541+
Marshal.WriteIntPtr(obj.pyHandle, ObjectOffset.magic(obj.tpHandle), IntPtr.Zero);
528542
}
529-
obj.gcHandle = default;
543+
XDecref(obj.pyHandle);
530544
}
531545
ManagedType.ClearTrackedObjects();
532546
}

0 commit comments

Comments
 (0)