@@ -266,6 +266,23 @@ hashtable_unicode_compare(const void *key1, const void *key2)
266
266
}
267
267
}
268
268
269
+ /* Return true if this interpreter should share the main interpreter's
270
+ intern_dict. That's important for interpreters which load basic
271
+ single-phase init extension modules (m_size == -1). There could be interned
272
+ immortal strings that are shared between interpreters, due to the
273
+ PyDict_Update(mdict, m_copy) call in import_find_extension().
274
+
275
+ It's not safe to deallocate those strings until all interpreters that
276
+ potentially use them are freed. By storing them in the main interpreter, we
277
+ ensure they get freed after all other interpreters are freed.
278
+ */
279
+ static bool
280
+ has_shared_intern_dict (PyInterpreterState * interp )
281
+ {
282
+ PyInterpreterState * main_interp = _PyInterpreterState_Main ();
283
+ return interp != main_interp && interp -> feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC ;
284
+ }
285
+
269
286
static int
270
287
init_interned_dict (PyInterpreterState * interp )
271
288
{
@@ -284,9 +301,16 @@ init_interned_dict(PyInterpreterState *interp)
284
301
}
285
302
}
286
303
assert (get_interned_dict (interp ) == NULL );
287
- PyObject * interned = interned = PyDict_New ();
288
- if (interned == NULL ) {
289
- return -1 ;
304
+ PyObject * interned ;
305
+ if (has_shared_intern_dict (interp )) {
306
+ interned = get_interned_dict (_PyInterpreterState_Main ());
307
+ Py_INCREF (interned );
308
+ }
309
+ else {
310
+ interned = PyDict_New ();
311
+ if (interned == NULL ) {
312
+ return -1 ;
313
+ }
290
314
}
291
315
_Py_INTERP_CACHED_OBJECT (interp , interned_strings ) = interned ;
292
316
return 0 ;
@@ -297,7 +321,10 @@ clear_interned_dict(PyInterpreterState *interp)
297
321
{
298
322
PyObject * interned = get_interned_dict (interp );
299
323
if (interned != NULL ) {
300
- PyDict_Clear (interned );
324
+ if (!has_shared_intern_dict (interp )) {
325
+ // only clear if the dict belongs to this interpreter
326
+ PyDict_Clear (interned );
327
+ }
301
328
Py_DECREF (interned );
302
329
_Py_INTERP_CACHED_OBJECT (interp , interned_strings ) = NULL ;
303
330
}
@@ -14861,6 +14888,13 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
14861
14888
}
14862
14889
assert (PyDict_CheckExact (interned ));
14863
14890
14891
+ if (has_shared_intern_dict (interp )) {
14892
+ // the dict doesn't belong to this interpreter, skip the debug
14893
+ // checks on it and just clear the pointer to it
14894
+ clear_interned_dict (interp );
14895
+ return ;
14896
+ }
14897
+
14864
14898
/* TODO:
14865
14899
* Currently, the runtime is not able to guarantee that it can exit without
14866
14900
* allocations that carry over to a future initialization of Python within
@@ -15364,8 +15398,10 @@ _PyUnicode_Fini(PyInterpreterState *interp)
15364
15398
{
15365
15399
struct _Py_unicode_state * state = & interp -> unicode ;
15366
15400
15367
- // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
15368
- assert (get_interned_dict (interp ) == NULL );
15401
+ if (!has_shared_intern_dict (interp )) {
15402
+ // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini()
15403
+ assert (get_interned_dict (interp ) == NULL );
15404
+ }
15369
15405
15370
15406
_PyUnicode_FiniEncodings (& state -> fs_codec );
15371
15407
0 commit comments