Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcb4bb9a

Browse files
committed
use a special class to stub .NET types that no longer exist after a domain reload
1 parentb1c9f5b commitcb4bb9a

File tree

12 files changed

+134
-89
lines changed

12 files changed

+134
-89
lines changed

‎src/runtime/ReflectedClrType.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace Python.Runtime;
99
internalsealedclassReflectedClrType:PyType
1010
{
1111
privateReflectedClrType(StolenReferencereference):base(reference,prevalidated:true){}
12+
internalReflectedClrType(ReflectedClrTypeoriginal):base(original,prevalidated:true){}
1213

1314
internalClassBaseImpl=>(ClassBase)ManagedType.GetManagedObject(this)!;
1415

@@ -19,12 +20,10 @@ private ReflectedClrType(StolenReference reference) : base(reference, prevalidat
1920
/// Returned <see cref="ReflectedClrType"/> might be partially initialized.
2021
/// If you need fully initialized type, use <see cref="GetOrInitialize(ClassBase, Type)"/>
2122
/// </remarks>
22-
publicstaticReflectedClrTypeGetOrCreate(Typetype,outClassBaseimpl)
23+
publicstaticReflectedClrTypeGetOrCreate(Typetype)
2324
{
2425
if(ClassManager.cache.TryGetValue(type,outvarpyType))
2526
{
26-
impl=(ClassBase)ManagedType.GetManagedObject(pyType)!;
27-
Debug.Assert(implis notnull);
2827
returnpyType;
2928
}
3029

@@ -34,7 +33,7 @@ public static ReflectedClrType GetOrCreate(Type type, out ClassBase impl)
3433
pyType=AllocateClass(type);
3534
ClassManager.cache.Add(type,pyType);
3635

37-
impl=ClassManager.CreateClass(type);
36+
varimpl=ClassManager.CreateClass(type);
3837

3938
TypeManager.InitializeClassCore(type,pyType,impl);
4039

@@ -52,11 +51,16 @@ internal void Restore(InterDomainContext context)
5251
{
5352
varcb=context.Storage.GetValue<ClassBase>("impl");
5453

54+
cb.Load(this,context);
55+
56+
Restore(cb);
57+
}
58+
59+
internalvoidRestore(ClassBasecb)
60+
{
5561
ClassManager.InitClassBase(cb.type.Value,cb,this);
5662

5763
TypeManager.InitializeClass(this,cb,cb.type.Value);
58-
59-
cb.Load(this,context);
6064
}
6165

6266
internalstaticNewReferenceCreateSubclass(ClassBasebaseClass,
@@ -71,7 +75,7 @@ internal static NewReference CreateSubclass(ClassBase baseClass,
7175
ns,
7276
assembly);
7377

74-
varpy_type=GetOrCreate(subType,out_);
78+
varpy_type=GetOrCreate(subType);
7579

7680
// by default the class dict will have all the C# methods in it, but as this is a
7781
// derived class we want the python overrides in there instead if they exist.

‎src/runtime/UnloadedClass.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
usingSystem;
2+
3+
namespacePython.Runtime;
4+
5+
[Serializable]
6+
internalclassUnloadedClass:ClassBase
7+
{
8+
readonlystringname;
9+
10+
internalUnloadedClass(stringname):base(typeof(object))
11+
{
12+
this.name=name;
13+
}
14+
15+
publicstaticNewReferencetp_new(BorrowedReferencetp,BorrowedReferenceargs,BorrowedReferencekw)
16+
{
17+
varself=(UnloadedClass)GetManagedObject(tp)!;
18+
returnself.RaiseTypeError();
19+
}
20+
21+
publicoverrideNewReferencetype_subscript(BorrowedReferenceidx)=>RaiseTypeError();
22+
23+
privateNewReferenceRaiseTypeError()
24+
=>Exceptions.RaiseTypeError("The .NET type no longer exists: "+name);
25+
26+
internaloverrideboolCanSubclass()=>false;
27+
}

‎src/runtime/classmanager.cs

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ public static void Reset()
5656

5757
internalstaticvoidRemoveClasses()
5858
{
59+
foreach(var@classincache.Values)
60+
{
61+
@class.Dispose();
62+
}
5963
cache.Clear();
6064
}
6165

@@ -81,11 +85,6 @@ internal static ClassManagerState SaveRuntimeData()
8185
varcontexts=newDictionary<ReflectedClrType,InterDomainContext>();
8286
foreach(varclsincache)
8387
{
84-
if(!cls.Key.Valid)
85-
{
86-
// Don't serialize an invalid class
87-
continue;
88-
}
8988
varcontext=contexts[cls.Value]=newInterDomainContext();
9089
varcb=(ClassBase)ManagedType.GetManagedObject(cls.Value)!;
9190
cb.Save(cls.Value,context);
@@ -129,31 +128,32 @@ internal static void RestoreRuntimeData(ClassManagerState storage)
129128
varcontexts=storage.Contexts;
130129
foreach(varpairincache)
131130
{
132-
if(!pair.Key.Valid)
131+
varcontext=contexts[pair.Value];
132+
if(pair.Key.Valid)
133+
{
134+
pair.Value.Restore(context);
135+
}
136+
else
133137
{
134138
invalidClasses.Add(pair);
135-
continue;
139+
varcb=newUnloadedClass(pair.Key.Name);
140+
cb.Load(pair.Value,context);
141+
pair.Value.Restore(cb);
136142
}
137-
138-
pair.Value.Restore(contexts[pair.Value]);
139-
}
140-
141-
foreach(varpairininvalidClasses)
142-
{
143-
cache.Remove(pair.Key);
144-
pair.Value.Dispose();
145143
}
146144
}
147145

148146
/// <summary>
149147
/// Return the ClassBase-derived instance that implements a particular
150148
/// reflected managed type, creating it if it doesn't yet exist.
151149
/// </summary>
152-
internalstaticReflectedClrTypeGetClass(Typetype)=>ReflectedClrType.GetOrCreate(type,out_);
150+
internalstaticReflectedClrTypeGetClass(Typetype)=>ReflectedClrType.GetOrCreate(type);
153151
internalstaticClassBaseGetClassImpl(Typetype)
154152
{
155-
ReflectedClrType.GetOrCreate(type,outvarcb);
156-
returncb;
153+
varpyType=GetClass(type);
154+
varimpl=(ClassBase)ManagedType.GetManagedObject(pyType)!;
155+
Debug.Assert(implis notnull);
156+
returnimpl!;
157157
}
158158

159159

@@ -236,22 +236,11 @@ internal static void InitClassBase(Type type, ClassBase impl, PyType pyType)
236236
varitem=iter.Value;
237237
varname=iter.Key;
238238
impl.dotNetMembers.Add(name);
239-
switch(item)
240-
{
241-
caseClassBasenestedClass:
242-
Runtime.PyDict_SetItemString(dict,name,GetClass(nestedClass.type.Value));
243-
break;
244-
caseExtensionTypeextension:
245-
using(varpyRef=extension.Alloc())
246-
{
247-
Runtime.PyDict_SetItemString(dict,name,pyRef.Borrow());
248-
}
249-
break;
250-
default:
251-
thrownewNotSupportedException();
252-
}
239+
Runtime.PyDict_SetItemString(dict,name,item);
253240
if(ClassBase.CilToPyOpMap.TryGetValue(name,outvarpyOp)
254-
&&itemisMethodObjectmethod)
241+
// workaround for unintialized types crashing in GetManagedObject
242+
&&itemis notReflectedClrType
243+
&&ManagedType.GetManagedObject(item)isMethodObjectmethod)
255244
{
256245
impl.richcompare.Add(pyOp,method);
257246
}
@@ -347,7 +336,7 @@ private static ClassInfo GetClassInfo(Type type)
347336
varci=newClassInfo();
348337
varmethods=newDictionary<string,List<MethodInfo>>();
349338
MethodInfometh;
350-
ManagedTypeob;
339+
ExtensionTypeob;
351340
stringname;
352341
Typetp;
353342
inti,n;
@@ -472,7 +461,7 @@ private static ClassInfo GetClassInfo(Type type)
472461
}
473462

474463
ob=newPropertyObject(pi);
475-
ci.members[pi.Name]=ob;
464+
ci.members[pi.Name]=ob.AllocObject();
476465
continue;
477466

478467
caseMemberTypes.Field:
@@ -482,7 +471,7 @@ private static ClassInfo GetClassInfo(Type type)
482471
continue;
483472
}
484473
ob=newFieldObject(fi);
485-
ci.members[mi.Name]=ob;
474+
ci.members[mi.Name]=ob.AllocObject();
486475
continue;
487476

488477
caseMemberTypes.Event:
@@ -494,7 +483,7 @@ private static ClassInfo GetClassInfo(Type type)
494483
ob=ei.AddMethod.IsStatic
495484
?newEventBinding(ei)
496485
:newEventObject(ei);
497-
ci.members[ei.Name]=ob;
486+
ci.members[ei.Name]=ob.AllocObject();
498487
continue;
499488

500489
caseMemberTypes.NestedType:
@@ -506,9 +495,8 @@ private static ClassInfo GetClassInfo(Type type)
506495
}
507496
// Note the given instance might be uninitialized
508497
varpyType=GetClass(tp);
509-
ob=ManagedType.GetManagedObject(pyType)!;
510-
Debug.Assert(obis notnull);
511-
ci.members[mi.Name]=ob;
498+
// make a copy, that could be disposed later
499+
ci.members[mi.Name]=newReflectedClrType(pyType);
512500
continue;
513501
}
514502
}
@@ -519,18 +507,18 @@ private static ClassInfo GetClassInfo(Type type)
519507
varmlist=iter.Value.ToArray();
520508

521509
ob=newMethodObject(type,name,mlist);
522-
ci.members[name]=ob;
510+
ci.members[name]=ob.AllocObject();
523511
if(mlist.Any(OperatorMethod.IsOperatorMethod))
524512
{
525513
stringpyName=OperatorMethod.GetPyMethodName(name);
526514
stringpyNameReverse=OperatorMethod.ReversePyMethodName(pyName);
527515
OperatorMethod.FilterMethods(mlist,outvarforwardMethods,outvarreverseMethods);
528516
// Only methods where the left operand is the declaring type.
529517
if(forwardMethods.Length>0)
530-
ci.members[pyName]=newMethodObject(type,name,forwardMethods);
518+
ci.members[pyName]=newMethodObject(type,name,forwardMethods).AllocObject();
531519
// Only methods where only the right operand is the declaring type.
532520
if(reverseMethods.Length>0)
533-
ci.members[pyNameReverse]=newMethodObject(type,name,reverseMethods);
521+
ci.members[pyNameReverse]=newMethodObject(type,name,reverseMethods).AllocObject();
534522
}
535523
}
536524

@@ -563,7 +551,7 @@ private static ClassInfo GetClassInfo(Type type)
563551
privateclassClassInfo
564552
{
565553
publicIndexer?indexer;
566-
publicreadonlyDictionary<string,ManagedType>members=new();
554+
publicreadonlyDictionary<string,PyObject>members=new();
567555

568556
internalClassInfo()
569557
{

‎src/runtime/extensiontype.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public virtual NewReference Alloc()
4040
returnpy.AnalyzerWorkaround();
4141
}
4242

43+
publicPyObjectAllocObject()=>newPyObject(Alloc().Steal());
44+
4345
// "borrowed" references
4446
internalstaticreadonlyHashSet<IntPtr>loadedExtensions=new();
4547
voidSetupGc(BorrowedReferenceob,BorrowedReferencetp)

‎src/runtime/importhook.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
usingSystem;
22
usingSystem.Collections.Concurrent;
33
usingSystem.Collections.Generic;
4+
usingSystem.Diagnostics;
45

56
usingPython.Runtime.StateSerialization;
67

@@ -98,6 +99,7 @@ private static Dictionary<PyString, PyObject> GetDotNetModules()
9899
BorrowedReferencepyModules=Runtime.PyImport_GetModuleDict();
99100
usingvaritems=Runtime.PyDict_Items(pyModules);
100101
nintlength=Runtime.PyList_Size(items.BorrowOrThrow());
102+
Debug.Assert(length>=0);
101103
varmodules=newDictionary<PyString,PyObject>();
102104
for(ninti=0;i<length;i++)
103105
{

‎src/runtime/metatype.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ public static void tp_dealloc(NewReference lastRef)
289289
{
290290
// Fix this when we dont cheat on the handle for subclasses!
291291

292-
varflags=(TypeFlags)Util.ReadCLong(lastRef.Borrow(),TypeOffset.tp_flags);
292+
varflags=PyType.GetFlags(lastRef.Borrow());
293293
if((flags&TypeFlags.Subclass)==0)
294294
{
295295
GetGCHandle(lastRef.Borrow()).Free();

‎src/runtime/native/TypeOffset.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ public static int GetSlotOffset(string slotName)
115115
returnSlotOffsets[slotName];
116116
}
117117

118+
publicstaticstring?GetSlotName(intoffset)
119+
=>SlotOffsets.FirstOrDefault(kv=>kv.Value==offset).Key;
120+
118121
staticreadonlyHashSet<string>slotNames=newHashSet<string>();
119122
internalstaticboolIsSupportedSlotName(stringname)=>slotNames.Contains(name);
120123

‎src/runtime/pyobject.cs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public partial class PyObject : DynamicObject, IDisposable
2323
/// <summary>
2424
/// Trace stack for PyObject's construction
2525
/// </summary>
26-
publicStackTraceTraceback{get;privateset;}
26+
publicStackTraceTraceback{get;}=newStackTrace(1);
2727
#endif
2828

2929
protectedinternalIntPtrrawPtr=IntPtr.Zero;
@@ -49,9 +49,6 @@ internal PyObject(IntPtr ptr)
4949

5050
rawPtr=ptr;
5151
Finalizer.Instance.ThrottledCollect();
52-
#ifTRACE_ALLOC
53-
Traceback=newStackTrace(1);
54-
#endif
5552
}
5653

5754
[Obsolete("for testing purposes only")]
@@ -62,9 +59,6 @@ internal PyObject(IntPtr ptr, bool skipCollect)
6259
rawPtr=ptr;
6360
if(!skipCollect)
6461
Finalizer.Instance.ThrottledCollect();
65-
#ifTRACE_ALLOC
66-
Traceback=newStackTrace(1);
67-
#endif
6862
}
6963

7064
/// <summary>
@@ -78,9 +72,15 @@ internal PyObject(BorrowedReference reference)
7872

7973
rawPtr=newNewReference(reference).DangerousMoveToPointer();
8074
Finalizer.Instance.ThrottledCollect();
81-
#ifTRACE_ALLOC
82-
Traceback=newStackTrace(1);
83-
#endif
75+
}
76+
77+
internalPyObject(BorrowedReferencereference,boolskipCollect)
78+
{
79+
if(reference.IsNull)thrownewArgumentNullException(nameof(reference));
80+
81+
rawPtr=newNewReference(reference).DangerousMoveToPointer();
82+
if(!skipCollect)
83+
Finalizer.Instance.ThrottledCollect();
8484
}
8585

8686
internalPyObject(inStolenReferencereference)
@@ -89,9 +89,6 @@ internal PyObject(in StolenReference reference)
8989

9090
rawPtr=reference.DangerousGetAddressOrNull();
9191
Finalizer.Instance.ThrottledCollect();
92-
#ifTRACE_ALLOC
93-
Traceback=newStackTrace(1);
94-
#endif
9592
}
9693

9794
// Ensure that encapsulated Python object is decref'ed appropriately

‎src/runtime/runtime.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,10 @@ private static void MoveClrInstancesOnwershipToPython()
479479
}
480480
}
481481

482-
foreach(IntPtrobjWithGcHandleinExtensionType.loadedExtensions.Concat(CLRObject.reflectedObjects).ToArray())
482+
foreach(IntPtrobjWithGcHandleinExtensionType.loadedExtensions
483+
.Concat(CLRObject.reflectedObjects)
484+
.ToArray()
485+
)
483486
{
484487
var@ref=newBorrowedReference(objWithGcHandle);
485488
GCHandle?handle=ManagedType.TryGetGCHandle(@ref);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp