From 58a993957abec7e47acb20376d2753051fa75452 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 20 May 2021 12:08:05 +0200 Subject: bpo-44131: Py_FrozenMain() uses PyConfig_SetBytesArgv() (GH-26201) Moreover, Py_FrozenMain() relies on Py_InitializeFromConfig() to handle the PYTHONUNBUFFERED environment variable and configure C stdio streams like stdout (make the stream unbuffered). --- Lib/test/test_embed.py | 10 ++++-- Programs/test_frozenmain.h | 46 ++++++++++++------------- Programs/test_frozenmain.py | 11 ++++-- Python/frozenmain.c | 84 ++++++++------------------------------------- 4 files changed, 51 insertions(+), 100 deletions(-) diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index c68a662..f4a18fd 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -1484,14 +1484,18 @@ class MiscTests(EmbeddingTestsMixin, unittest.TestCase): @unittest.skipIf(os.name == 'nt', 'Py_FrozenMain is not exported on Windows') def test_frozenmain(self): - out, err = self.run_embedded_interpreter("test_frozenmain") - exe = os.path.realpath('./argv0') + env = dict(os.environ) + env['PYTHONUNBUFFERED'] = '1' + out, err = self.run_embedded_interpreter("test_frozenmain", env=env) + executable = os.path.realpath('./argv0') expected = textwrap.dedent(f""" Frozen Hello World sys.argv ['./argv0', '-E', 'arg1', 'arg2'] config program_name: ./argv0 - config executable: {exe} + config executable: {executable} config use_environment: 1 + config configure_c_stdio: 1 + config buffered_stdio: 0 """).lstrip() self.assertEqual(out, expected) diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index e680b80..a6c2e42 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,30 +1,28 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,4,0,0,0,64,0,0,0,115,106,0,0,0,100,0, + 0,7,0,0,0,64,0,0,0,115,86,0,0,0,100,0, 100,1,108,0,90,0,100,0,100,1,108,1,90,1,101,2, 100,2,131,1,1,0,101,2,100,3,101,0,106,3,131,2, - 1,0,101,1,160,4,161,0,100,4,25,0,90,5,101,2, - 100,5,101,5,100,6,25,0,155,0,157,2,131,1,1,0, - 101,2,100,7,101,5,100,8,25,0,155,0,157,2,131,1, - 1,0,101,2,100,9,101,5,100,10,25,0,155,0,157,2, - 131,1,1,0,100,1,83,0,41,11,233,0,0,0,0,78, - 122,18,70,114,111,122,101,110,32,72,101,108,108,111,32,87, - 111,114,108,100,122,8,115,121,115,46,97,114,103,118,218,6, - 99,111,110,102,105,103,122,21,99,111,110,102,105,103,32,112, - 114,111,103,114,97,109,95,110,97,109,101,58,32,90,12,112, - 114,111,103,114,97,109,95,110,97,109,101,122,19,99,111,110, - 102,105,103,32,101,120,101,99,117,116,97,98,108,101,58,32, - 218,10,101,120,101,99,117,116,97,98,108,101,122,24,99,111, - 110,102,105,103,32,117,115,101,95,101,110,118,105,114,111,110, - 109,101,110,116,58,32,90,15,117,115,101,95,101,110,118,105, - 114,111,110,109,101,110,116,41,6,218,3,115,121,115,90,17, - 95,116,101,115,116,105,110,116,101,114,110,97,108,99,97,112, - 105,218,5,112,114,105,110,116,218,4,97,114,103,118,90,11, - 103,101,116,95,99,111,110,102,105,103,115,114,2,0,0,0, - 169,0,114,7,0,0,0,114,7,0,0,0,250,18,116,101, - 115,116,95,102,114,111,122,101,110,109,97,105,110,46,112,121, - 218,8,60,109,111,100,117,108,101,62,1,0,0,0,115,16, - 0,0,0,8,3,8,1,8,2,12,1,12,1,18,1,18, - 1,22,1,243,0,0,0,0, + 1,0,101,1,160,4,161,0,100,4,25,0,90,5,100,5, + 68,0,93,14,90,6,101,2,100,6,101,6,155,0,100,7, + 101,5,101,6,25,0,155,0,157,4,131,1,1,0,113,26, + 100,1,83,0,41,8,233,0,0,0,0,78,122,18,70,114, + 111,122,101,110,32,72,101,108,108,111,32,87,111,114,108,100, + 122,8,115,121,115,46,97,114,103,118,218,6,99,111,110,102, + 105,103,41,5,90,12,112,114,111,103,114,97,109,95,110,97, + 109,101,218,10,101,120,101,99,117,116,97,98,108,101,90,15, + 117,115,101,95,101,110,118,105,114,111,110,109,101,110,116,90, + 17,99,111,110,102,105,103,117,114,101,95,99,95,115,116,100, + 105,111,90,14,98,117,102,102,101,114,101,100,95,115,116,100, + 105,111,122,7,99,111,110,102,105,103,32,122,2,58,32,41, + 7,218,3,115,121,115,90,17,95,116,101,115,116,105,110,116, + 101,114,110,97,108,99,97,112,105,218,5,112,114,105,110,116, + 218,4,97,114,103,118,90,11,103,101,116,95,99,111,110,102, + 105,103,115,114,2,0,0,0,218,3,107,101,121,169,0,114, + 8,0,0,0,114,8,0,0,0,250,18,116,101,115,116,95, + 102,114,111,122,101,110,109,97,105,110,46,112,121,218,8,60, + 109,111,100,117,108,101,62,1,0,0,0,115,16,0,0,0, + 8,3,8,1,8,2,12,1,12,1,8,1,26,7,4,249, + 243,0,0,0,0, }; diff --git a/Programs/test_frozenmain.py b/Programs/test_frozenmain.py index 928b9ea..53f5fd6 100644 --- a/Programs/test_frozenmain.py +++ b/Programs/test_frozenmain.py @@ -7,6 +7,11 @@ import _testinternalcapi print("Frozen Hello World") print("sys.argv", sys.argv) config = _testinternalcapi.get_configs()['config'] -print(f"config program_name: {config['program_name']}") -print(f"config executable: {config['executable']}") -print(f"config use_environment: {config['use_environment']}") +for key in ( + 'program_name', + 'executable', + 'use_environment', + 'configure_c_stdio', + 'buffered_stdio', +): + print(f"config {key}: {config[key]}") diff --git a/Python/frozenmain.c b/Python/frozenmain.c index c3104da..8743e08 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -20,74 +20,28 @@ Py_FrozenMain(int argc, char **argv) Py_ExitStatusException(status); } - const char *p; - int i, n, sts = 1; - int inspect = 0; - int unbuffered = 0; - char *oldloc = NULL; - wchar_t **argv_copy = NULL; - /* We need a second copies, as Python might modify the first one. */ - wchar_t **argv_copy2 = NULL; - - if (argc > 0) { - argv_copy = PyMem_RawMalloc(sizeof(wchar_t*) * argc); - argv_copy2 = PyMem_RawMalloc(sizeof(wchar_t*) * argc); - if (!argv_copy || !argv_copy2) { - fprintf(stderr, "out of memory\n"); - goto error; - } - } - PyConfig config; PyConfig_InitPythonConfig(&config); - config.pathconfig_warnings = 0; /* Suppress errors from getpath.c */ - - if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') { - inspect = 1; - } - if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') { - unbuffered = 1; - } - - if (unbuffered) { - setbuf(stdin, (char *)NULL); - setbuf(stdout, (char *)NULL); - setbuf(stderr, (char *)NULL); - } + // Suppress errors from getpath.c + config.pathconfig_warnings = 0; + // Don't parse command line options like -E + config.parse_argv = 0; - oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL)); - if (!oldloc) { - fprintf(stderr, "out of memory\n"); - goto error; + status = PyConfig_SetBytesArgv(&config, argc, argv); + if (PyStatus_Exception(status)) { + PyConfig_Clear(&config); + Py_ExitStatusException(status); } - setlocale(LC_ALL, ""); - for (i = 0; i < argc; i++) { - argv_copy[i] = Py_DecodeLocale(argv[i], NULL); - argv_copy2[i] = argv_copy[i]; - if (!argv_copy[i]) { - fprintf(stderr, - "Unable to decode the command line argument #%i\n", - i + 1); - argc = i; - goto error; - } + const char *p; + int inspect = 0; + if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') { + inspect = 1; } - setlocale(LC_ALL, oldloc); - PyMem_RawFree(oldloc); - oldloc = NULL; #ifdef MS_WINDOWS PyInitFrozenExtensions(); #endif /* MS_WINDOWS */ - if (argc >= 1) { - status = PyConfig_SetString(&config, &config.program_name, - argv_copy[0]); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } - } status = Py_InitializeFromConfig(&config); PyConfig_Clear(&config); @@ -104,9 +58,8 @@ Py_FrozenMain(int argc, char **argv) Py_GetVersion(), Py_GetCopyright()); } - PySys_SetArgv(argc, argv_copy); - - n = PyImport_ImportFrozenModule("__main__"); + int sts = 1; + int n = PyImport_ImportFrozenModule("__main__"); if (n == 0) { Py_FatalError("the __main__ module is not frozen"); } @@ -128,14 +81,5 @@ Py_FrozenMain(int argc, char **argv) if (Py_FinalizeEx() < 0) { sts = 120; } - -error: - PyMem_RawFree(argv_copy); - if (argv_copy2) { - for (i = 0; i < argc; i++) - PyMem_RawFree(argv_copy2[i]); - PyMem_RawFree(argv_copy2); - } - PyMem_RawFree(oldloc); return sts; } -- cgit v0.12