@@ -2213,3 +2213,40 @@ def requires_venv_with_pip():
2213
2213
# True if Python is built with the Py_DEBUG macro defined: if
2214
2214
# Python is built in debug mode (./configure --with-pydebug).
2215
2215
Py_DEBUG = hasattr (sys , 'gettotalrefcount' )
2216
+
2217
+
2218
+ def late_deletion (obj ):
2219
+ """
2220
+ Keep a Python alive as long as possible.
2221
+
2222
+ Create a reference cycle and store the cycle in an object deleted late in
2223
+ Python finalization. Try to keep the object alive until the very last
2224
+ garbage collection.
2225
+
2226
+ The function keeps a strong reference by design. It should be called in a
2227
+ subprocess to not mark a test as "leaking a reference".
2228
+ """
2229
+
2230
+ # Late CPython finalization:
2231
+ # - finalize_interp_clear()
2232
+ # - _PyInterpreterState_Clear(): Clear PyInterpreterState members
2233
+ # (ex: codec_search_path, before_forkers)
2234
+ # - clear os.register_at_fork() callbacks
2235
+ # - clear codecs.register() callbacks
2236
+
2237
+ ref_cycle = [obj ]
2238
+ ref_cycle .append (ref_cycle )
2239
+
2240
+ # Store a reference in PyInterpreterState.codec_search_path
2241
+ import codecs
2242
+ def search_func (encoding ):
2243
+ return None
2244
+ search_func .reference = ref_cycle
2245
+ codecs .register (search_func )
2246
+
2247
+ if hasattr (os , 'register_at_fork' ):
2248
+ # Store a reference in PyInterpreterState.before_forkers
2249
+ def atfork_func ():
2250
+ pass
2251
+ atfork_func .reference = ref_cycle
2252
+ os .register_at_fork (before = atfork_func )
0 commit comments