@@ -30,7 +30,11 @@ static PyObject *import_add_module(PyThreadState *tstate, PyObject *name);
3030/* This table is defined in config.c: */
3131extern struct _inittab _PyImport_Inittab [];
3232
33+ // This is not used after Py_Initialize() is called.
34+ // (See _PyRuntimeState.imports.inittab.)
3335struct _inittab * PyImport_Inittab = _PyImport_Inittab ;
36+ // When we dynamically allocate a larger table for PyImport_ExtendInittab(),
37+ // we track the pointer here so we can deallocate it during finalization.
3438static struct _inittab * inittab_copy = NULL ;
3539
3640/*[clinic input]
@@ -218,6 +222,38 @@ _imp_release_lock_impl(PyObject *module)
218222 Py_RETURN_NONE ;
219223}
220224
225+ PyStatus
226+ _PyImport_Init (void )
227+ {
228+ if (_PyRuntime .imports .inittab != NULL ) {
229+ return _PyStatus_ERR ("global import state already initialized" );
230+ }
231+ PyStatus status = _PyStatus_OK ();
232+
233+ size_t size ;
234+ for (size = 0 ; PyImport_Inittab [size ].name != NULL ; size ++ )
235+ ;
236+ size ++ ;
237+
238+ /* Force default raw memory allocator to get a known allocator to be able
239+ to release the memory in _PyImport_Fini() */
240+ PyMemAllocatorEx old_alloc ;
241+ _PyMem_SetDefaultAllocator (PYMEM_DOMAIN_RAW , & old_alloc );
242+
243+ /* Make the copy. */
244+ struct _inittab * copied = PyMem_RawMalloc (size * sizeof (struct _inittab ));
245+ if (copied == NULL ) {
246+ status = PyStatus_NoMemory ();
247+ goto done ;
248+ }
249+ memcpy (copied , PyImport_Inittab , size * sizeof (struct _inittab ));
250+ _PyRuntime .imports .inittab = copied ;
251+
252+ done :
253+ PyMem_SetAllocator (PYMEM_DOMAIN_RAW , & old_alloc );
254+ return status ;
255+ }
256+
221257static inline void _extensions_cache_clear (void );
222258
223259void
@@ -228,6 +264,17 @@ _PyImport_Fini(void)
228264 PyThread_free_lock (import_lock );
229265 import_lock = NULL ;
230266 }
267+
268+ /* Use the same memory allocator as _PyImport_Init(). */
269+ PyMemAllocatorEx old_alloc ;
270+ _PyMem_SetDefaultAllocator (PYMEM_DOMAIN_RAW , & old_alloc );
271+
272+ /* Free memory allocated by _PyImport_Init() */
273+ struct _inittab * inittab = _PyRuntime .imports .inittab ;
274+ _PyRuntime .imports .inittab = NULL ;
275+ PyMem_RawFree (inittab );
276+
277+ PyMem_SetAllocator (PYMEM_DOMAIN_RAW , & old_alloc );
231278}
232279
233280void
@@ -889,9 +936,10 @@ static int
889936is_builtin (PyObject * name )
890937{
891938 int i ;
892- for (i = 0 ; PyImport_Inittab [i ].name != NULL ; i ++ ) {
893- if (_PyUnicode_EqualToASCIIString (name , PyImport_Inittab [i ].name )) {
894- if (PyImport_Inittab [i ].initfunc == NULL )
939+ struct _inittab * inittab = _PyRuntime .imports .inittab ;
940+ for (i = 0 ; inittab [i ].name != NULL ; i ++ ) {
941+ if (_PyUnicode_EqualToASCIIString (name , inittab [i ].name )) {
942+ if (inittab [i ].initfunc == NULL )
895943 return -1 ;
896944 else
897945 return 1 ;
@@ -984,7 +1032,7 @@ create_builtin(PyThreadState *tstate, PyObject *name, PyObject *spec)
9841032 }
9851033
9861034 PyObject * modules = tstate -> interp -> modules ;
987- for (struct _inittab * p = PyImport_Inittab ; p -> name != NULL ; p ++ ) {
1035+ for (struct _inittab * p = _PyRuntime . imports . inittab ; p -> name != NULL ; p ++ ) {
9881036 if (_PyUnicode_EqualToASCIIString (name , p -> name )) {
9891037 if (p -> initfunc == NULL ) {
9901038 /* Cannot re-init internal module ("sys" or "builtins") */
@@ -2592,6 +2640,10 @@ PyImport_ExtendInittab(struct _inittab *newtab)
25922640 size_t i , n ;
25932641 int res = 0 ;
25942642
2643+ if (_PyRuntime .imports .inittab != NULL ) {
2644+ Py_FatalError ("PyImport_ExtendInittab() may be be called after Py_Initialize()" );
2645+ }
2646+
25952647 /* Count the number of entries in both tables */
25962648 for (n = 0 ; newtab [n ].name != NULL ; n ++ )
25972649 ;
@@ -2636,6 +2688,10 @@ PyImport_AppendInittab(const char *name, PyObject* (*initfunc)(void))
26362688{
26372689 struct _inittab newtab [2 ];
26382690
2691+ if (_PyRuntime .imports .inittab != NULL ) {
2692+ Py_FatalError ("PyImport_AppendInittab() may be be called after Py_Initialize()" );
2693+ }
2694+
26392695 memset (newtab , '\0' , sizeof newtab );
26402696
26412697 newtab [0 ].name = name ;
0 commit comments