self.assertEqual(out, '')
self.assertEqual(err, '')
+ def test_initialize_pymain(self):
+ """
+ bpo-34008: Calling Py_Main() after Py_Initialize() must not fail.
+ """
+ out, err = self.run_embedded_interpreter("initialize_pymain")
+ self.assertEqual(out.rstrip(), "Py_Main() after Py_Initialize: sys.argv=['-c', 'arg2']")
+ self.assertEqual(err, '')
+
if __name__ == "__main__":
unittest.main()
--- /dev/null
+Py_Main() can again be called after Py_Initialize(), as in Python 3.6.
pymain_init_stdio(pymain);
- pymain->err = _Py_InitializeCore(&pymain->config);
- if (_Py_INIT_FAILED(pymain->err)) {
- _Py_FatalInitError(pymain->err);
+ /* bpo-34008: For backward compatibility reasons, calling Py_Main() after
+ Py_Initialize() ignores the new configuration. */
+ if (!_PyRuntime.initialized) {
+ pymain->err = _Py_InitializeCore(&pymain->config);
+ if (_Py_INIT_FAILED(pymain->err)) {
+ _Py_FatalInitError(pymain->err);
+ }
}
if (pymain_init_python_main(pymain) < 0) {
return 0;
}
+static int test_initialize_pymain(void)
+{
+ wchar_t *argv[] = {L"PYTHON", L"-c",
+ L"import sys; print(f'Py_Main() after Py_Initialize: sys.argv={sys.argv}')",
+ L"arg2"};
+ _testembed_Py_Initialize();
+
+ /* bpo-34008: Calling Py_Main() after Py_Initialize() must not crash */
+ Py_Main(Py_ARRAY_LENGTH(argv), argv);
+
+ Py_Finalize();
+
+ return 0;
+}
+
/* *********************************************************
* List of test cases and the function that implements it.
{ "pre_initialization_sys_options", test_pre_initialization_sys_options },
{ "bpo20891", test_bpo20891 },
{ "initialize_twice", test_initialize_twice },
+ { "initialize_pymain", test_initialize_pymain },
{ NULL, NULL }
};
return _Py_INIT_OK();
}
+/* Py_Initialize() has already been called: update the main interpreter
+ configuration. Example of bpo-34008: Py_Main() called after
+ Py_Initialize(). */
+static _PyInitError
+_Py_ReconfigureMainInterpreter(PyInterpreterState *interp,
+ const _PyMainInterpreterConfig *config)
+{
+ if (config->argv != NULL) {
+ int res = PyDict_SetItemString(interp->sysdict, "argv", config->argv);
+ if (res < 0) {
+ return _Py_INIT_ERR("fail to set sys.argv");
+ }
+ }
+ return _Py_INIT_OK();
+}
+
/* Update interpreter state based on supplied configuration settings
*
* After calling this function, most of the restrictions on the interpreter
if (!_PyRuntime.core_initialized) {
return _Py_INIT_ERR("runtime core not initialized");
}
- if (_PyRuntime.initialized) {
- return _Py_INIT_ERR("main interpreter already initialized");
- }
/* Get current thread state and interpreter pointer */
tstate = PyThreadState_GET();
return _Py_INIT_ERR("failed to copy main interpreter config");
}
+ if (_PyRuntime.initialized) {
+ return _Py_ReconfigureMainInterpreter(interp, config);
+ }
+
if (interp->core_config._disable_importlib) {
/* Special mode for freeze_importlib: run with no import system
*