2222/* Use path starting with "./" avoids a search along the PATH */
2323#define PROGRAM_NAME L"./_testembed"
2424
25+ #define INIT_LOOPS 16
26+
2527// Ignore Py_DEPRECATED() compiler warnings: deprecated functions are
2628// tested on purpose here.
2729_Py_COMP_DIAG_PUSH
@@ -67,9 +69,8 @@ static int test_repeated_init_and_subinterpreters(void)
6769{
6870 PyThreadState * mainstate , * substate ;
6971 PyGILState_STATE gilstate ;
70- int i , j ;
7172
72- for (i = 0 ; i < 15 ; i ++ ) {
73+ for (int i = 1 ; i <= INIT_LOOPS ; i ++ ) {
7374 printf ("--- Pass %d ---\n" , i );
7475 _testembed_Py_Initialize ();
7576 mainstate = PyThreadState_Get ();
@@ -80,7 +81,7 @@ static int test_repeated_init_and_subinterpreters(void)
8081 print_subinterp ();
8182 PyThreadState_Swap (NULL );
8283
83- for (j = 0 ; j < 3 ; j ++ ) {
84+ for (int j = 0 ; j < 3 ; j ++ ) {
8485 substate = Py_NewInterpreter ();
8586 print_subinterp ();
8687 Py_EndInterpreter (substate );
@@ -96,6 +97,20 @@ static int test_repeated_init_and_subinterpreters(void)
9697 return 0 ;
9798}
9899
100+ #define EMBEDDED_EXT_NAME "embedded_ext"
101+
102+ static PyModuleDef embedded_ext = {
103+ PyModuleDef_HEAD_INIT ,
104+ .m_name = EMBEDDED_EXT_NAME ,
105+ .m_size = 0 ,
106+ };
107+
108+ static PyObject *
109+ PyInit_embedded_ext (void )
110+ {
111+ return PyModule_Create (& embedded_ext );
112+ }
113+
99114/*****************************************************
100115 * Test forcing a particular IO encoding
101116 *****************************************************/
@@ -1790,6 +1805,38 @@ static int list_frozen(void)
17901805}
17911806
17921807
1808+ static int test_repeated_init_and_inittab (void )
1809+ {
1810+ // bpo-44441: Py_RunMain() must reset PyImport_Inittab at exit.
1811+ // It must be possible to call PyImport_AppendInittab() or
1812+ // PyImport_ExtendInittab() before each Python initialization.
1813+ for (int i = 1 ; i <= INIT_LOOPS ; i ++ ) {
1814+ printf ("--- Pass %d ---\n" , i );
1815+
1816+ // Call PyImport_AppendInittab() at each iteration
1817+ if (PyImport_AppendInittab (EMBEDDED_EXT_NAME ,
1818+ & PyInit_embedded_ext ) != 0 ) {
1819+ fprintf (stderr , "PyImport_AppendInittab() failed\n" );
1820+ return 1 ;
1821+ }
1822+
1823+ // Initialize Python
1824+ wchar_t * argv [] = {PROGRAM_NAME , L"-c" , L"pass" };
1825+ PyConfig config ;
1826+ PyConfig_InitPythonConfig (& config );
1827+ config .isolated = 1 ;
1828+ config_set_argv (& config , Py_ARRAY_LENGTH (argv ), argv );
1829+ init_from_config_clear (& config );
1830+
1831+ // Py_RunMain() calls _PyImport_Fini2() which resets PyImport_Inittab
1832+ int exitcode = Py_RunMain ();
1833+ if (exitcode != 0 ) {
1834+ return exitcode ;
1835+ }
1836+ }
1837+ return 0 ;
1838+ }
1839+
17931840
17941841/* *********************************************************
17951842 * List of test cases and the function that implements it.
@@ -1810,8 +1857,10 @@ struct TestCase
18101857};
18111858
18121859static struct TestCase TestCases [] = {
1860+ // Python initialization
18131861 {"test_forced_io_encoding" , test_forced_io_encoding },
18141862 {"test_repeated_init_and_subinterpreters" , test_repeated_init_and_subinterpreters },
1863+ {"test_repeated_init_and_inittab" , test_repeated_init_and_inittab },
18151864 {"test_pre_initialization_api" , test_pre_initialization_api },
18161865 {"test_pre_initialization_sys_options" , test_pre_initialization_sys_options },
18171866 {"test_bpo20891" , test_bpo20891 },
@@ -1851,6 +1900,7 @@ static struct TestCase TestCases[] = {
18511900 {"test_run_main" , test_run_main },
18521901 {"test_get_argc_argv" , test_get_argc_argv },
18531902
1903+ // Audit
18541904 {"test_open_code_hook" , test_open_code_hook },
18551905 {"test_audit" , test_audit },
18561906 {"test_audit_subinterpreter" , test_audit_subinterpreter },
@@ -1860,11 +1910,13 @@ static struct TestCase TestCases[] = {
18601910 {"test_audit_run_startup" , test_audit_run_startup },
18611911 {"test_audit_run_stdin" , test_audit_run_stdin },
18621912
1913+ // Specific C API
18631914 {"test_unicode_id_init" , test_unicode_id_init },
18641915#ifndef MS_WINDOWS
18651916 {"test_frozenmain" , test_frozenmain },
18661917#endif
18671918
1919+ // Command
18681920 {"list_frozen" , list_frozen },
18691921 {NULL , NULL }
18701922};
0 commit comments