@@ -9,25 +9,33 @@ namespace Python.Runtime
99{
1010 class RuntimeState
1111 {
12+ public static bool ShouldRestoreObjects { get ; set ; } = false ;
13+ public static bool UseDummyGC { get ; set ; } = false ;
14+
1215 public static void Save ( )
1316 {
1417 if ( PySys_GetObject ( "dummy_gc" ) != IntPtr . Zero )
1518 {
1619 throw new Exception ( "Runtime State set already" ) ;
1720 }
1821
22+ IntPtr objs = IntPtr . Zero ;
23+ if ( ShouldRestoreObjects )
24+ {
25+ objs = PySet_New ( IntPtr . Zero ) ;
26+ foreach ( var obj in PyGCGetObjects ( ) )
27+ {
28+ AddObjPtrToSet ( objs , obj ) ;
29+ }
30+ }
31+
1932 var modules = PySet_New ( IntPtr . Zero ) ;
2033 foreach ( var name in GetModuleNames ( ) )
2134 {
2235 int res = PySet_Add ( modules , name ) ;
2336 PythonException . ThrowIfIsNotZero ( res ) ;
2437 }
2538
26- var objs = PySet_New ( IntPtr . Zero ) ;
27- foreach ( var obj in PyGCGetObjects ( ) )
28- {
29- AddObjPtrToSet ( objs , obj ) ;
30- }
3139
3240 var dummyGCHead = PyMem_Malloc ( Marshal . SizeOf ( typeof ( PyGC_Head ) ) ) ;
3341 unsafe
@@ -43,7 +51,6 @@ public static void Save()
4351 PythonException . ThrowIfIsNotZero ( res ) ;
4452 XDecref ( pyDummyGC ) ;
4553
46- AddObjPtrToSet ( objs , modules ) ;
4754 try
4855 {
4956 res = PySys_SetObject ( "initial_modules" , modules ) ;
@@ -54,17 +61,19 @@ public static void Save()
5461 XDecref ( modules ) ;
5562 }
5663
57- AddObjPtrToSet ( objs , objs ) ;
58- try
59- {
60- res = PySys_SetObject ( "initial_objs" , objs ) ;
61- PythonException . ThrowIfIsNotZero ( res ) ;
62- }
63- finally
64+ if ( ShouldRestoreObjects )
6465 {
65- XDecref ( objs ) ;
66+ AddObjPtrToSet ( objs , modules ) ;
67+ try
68+ {
69+ res = PySys_SetObject ( "initial_objs" , objs ) ;
70+ PythonException . ThrowIfIsNotZero ( res ) ;
71+ }
72+ finally
73+ {
74+ XDecref ( objs ) ;
75+ }
6676 }
67-
6877 }
6978 }
7079
@@ -77,7 +86,10 @@ public static void Restore()
7786 }
7887 var dummyGC = PyLong_AsVoidPtr ( dummyGCAddr ) ;
7988 ResotreModules ( dummyGC ) ;
80- RestoreObjects ( dummyGC ) ;
89+ if ( ShouldRestoreObjects )
90+ {
91+ RestoreObjects ( dummyGC ) ;
92+ }
8193 }
8294
8395 private static void ResotreModules ( IntPtr dummyGC )
@@ -92,16 +104,24 @@ private static void ResotreModules(IntPtr dummyGC)
92104 continue ;
93105 }
94106 var module = PyDict_GetItem ( modules , name ) ;
95- if ( _PyObject_GC_IS_TRACKED ( module ) )
107+
108+ if ( UseDummyGC && _PyObject_GC_IS_TRACKED ( module ) )
96109 {
97110 ExchangeGCChain ( module , dummyGC ) ;
98111 }
99- PyDict_DelItem ( modules , name ) ;
112+ if ( PyDict_DelItem ( modules , name ) != 0 )
113+ {
114+ PyErr_Print ( ) ;
115+ }
100116 }
101117 }
102118
103119 private static void RestoreObjects ( IntPtr dummyGC )
104120 {
121+ if ( ! UseDummyGC )
122+ {
123+ throw new Exception ( "To prevent crash by _PyObject_GC_UNTRACK in Python internal, UseDummyGC should be enabled when using ResotreObjects" ) ;
124+ }
105125 var intialObjs = PySys_GetObject ( "initial_objs" ) ;
106126 Debug . Assert ( intialObjs != null ) ;
107127 foreach ( var obj in PyGCGetObjects ( ) )
0 commit comments