[Python-checkins] bpo-32030: Add _PyCoreConfig.argv (#4934)

Victor Stinner webhook-mailer at python.org
Tue Dec 19 17:48:20 EST 2017


https://github.com/python/cpython/commit/c4bca951065f4b2b6833f6ce7a0721e863e2343e
commit: c4bca951065f4b2b6833f6ce7a0721e863e2343e
branch: master
author: Victor Stinner <victor.stinner at gmail.com>
committer: GitHub <noreply at github.com>
date: 2017-12-19T23:48:17+01:00
summary:

bpo-32030: Add _PyCoreConfig.argv (#4934)

* Add argc and argv to _PyCoreConfig
* _PyMainInterpreterConfig_Read() now builds its argv from
  _PyCoreConfig.arg
* Move _PyMain.env_warning_options into _Py_CommandLineDetails
* Reorder pymain_free()

files:
M Include/pylifecycle.h
M Include/pystate.h
M Modules/main.c

diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h
index 3ea8ad65088..77c4330ebcc 100644
--- a/Include/pylifecycle.h
+++ b/Include/pylifecycle.h
@@ -61,7 +61,9 @@ PyAPI_FUNC(int) _PyCoreConfig_Copy(
     _PyCoreConfig *config,
     const _PyCoreConfig *config2);
 
-PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *, _PyCoreConfig *);
+PyAPI_FUNC(_PyInitError) _PyMainInterpreterConfig_Read(
+    _PyMainInterpreterConfig *config,
+    const _PyCoreConfig *core_config);
 PyAPI_FUNC(void) _PyMainInterpreterConfig_Clear(_PyMainInterpreterConfig *);
 PyAPI_FUNC(int) _PyMainInterpreterConfig_Copy(
     _PyMainInterpreterConfig *config,
diff --git a/Include/pystate.h b/Include/pystate.h
index fff134a4970..ed5b6c9bd1a 100644
--- a/Include/pystate.h
+++ b/Include/pystate.h
@@ -47,10 +47,18 @@ typedef struct {
     wchar_t *home;          /* PYTHONHOME environment variable,
                                see also Py_SetPythonHome(). */
     wchar_t *program_name;  /* Program name, see also Py_GetProgramName() */
+
+    int argc;               /* Number of command line arguments,
+                               -1 means unset */
+    wchar_t **argv;         /* sys.argv, ignored if argc is negative */
 } _PyCoreConfig;
 
 #define _PyCoreConfig_INIT \
-    (_PyCoreConfig){.use_hash_seed = -1, .coerce_c_locale = -1, .utf8_mode = -1}
+    (_PyCoreConfig){ \
+        .use_hash_seed = -1, \
+        .coerce_c_locale = -1, \
+        .utf8_mode = -1, \
+        .argc = -1}
 /* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */
 
 /* Placeholders while working on the new configuration API
diff --git a/Modules/main.c b/Modules/main.c
index 360a0859d4c..59e535d6ae7 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -229,7 +229,7 @@ pymain_run_interactive_hook(void)
 
 
 static int
-pymain_run_module(wchar_t *modname, int set_argv0)
+pymain_run_module(const wchar_t *modname, int set_argv0)
 {
     PyObject *module, *runpy, *runmodule, *runargs, *result;
     runpy = PyImport_ImportModule("runpy");
@@ -279,7 +279,7 @@ pymain_run_module(wchar_t *modname, int set_argv0)
 }
 
 static PyObject *
-pymain_get_importer(wchar_t *filename)
+pymain_get_importer(const wchar_t *filename)
 {
     PyObject *sys_path0 = NULL, *importer;
 
@@ -384,9 +384,10 @@ typedef struct {
 } _Py_OptList;
 
 typedef struct {
-    wchar_t *filename;           /* Trailing arg without -c or -m */
+    wchar_t **argv;
+    const wchar_t *filename;     /* Trailing arg without -c or -m */
     wchar_t *command;            /* -c argument */
-    wchar_t *module;             /* -m argument */
+    const wchar_t *module;       /* -m argument */
     _Py_OptList warning_options; /* -W options */
     int print_help;              /* -h, -? options */
     int print_version;           /* -V option */
@@ -411,6 +412,7 @@ typedef struct {
     int legacy_windows_stdio;        /* Py_LegacyWindowsStdioFlag,
                                         PYTHONLEGACYWINDOWSSTDIO */
 #endif
+    _Py_OptList env_warning_options;  /* PYTHONWARNINGS env var */
 } _Py_CommandLineDetails;
 
 /* Structure used by Py_Main() to pass data to subfunctions */
@@ -429,16 +431,11 @@ typedef struct {
     int run_code;
     /* Error message if a function failed */
     _PyInitError err;
-    /* PYTHONWARNINGS env var */
-    _Py_OptList env_warning_options;
 
     int argc;
-    wchar_t **argv;
     int use_bytes_argv;
     char **bytes_argv;
-
-    int sys_argc;
-    wchar_t **sys_argv;
+    wchar_t **wchar_argv;
 } _PyMain;
 
 /* .cmdline is initialized to zeros */
@@ -462,118 +459,141 @@ pymain_optlist_clear(_Py_OptList *list)
 }
 
 
-/* Free global variables which cannot be freed in Py_Finalize():
-   configuration options set before Py_Initialize() which should
-   remain valid after Py_Finalize(), since Py_Initialize()/Py_Finalize() can
-   be called multiple times.
-
-   Called with the current memory allocators. */
 static void
-pymain_free_globals(_PyMain *pymain)
+clear_argv(int argc, wchar_t **argv)
 {
-    _PyPathConfig_Clear(&_Py_path_config);
-    _PyImport_Fini2();
-
-#ifdef __INSURE__
-    /* Insure++ is a memory analysis tool that aids in discovering
-     * memory leaks and other memory problems.  On Python exit, the
-     * interned string dictionaries are flagged as being in use at exit
-     * (which it is).  Under normal circumstances, this is fine because
-     * the memory will be automatically reclaimed by the system.  Under
-     * memory debugging, it's a huge source of useless noise, so we
-     * trade off slower shutdown for less distraction in the memory
-     * reports.  -baw
-     */
-    _Py_ReleaseInternedUnicodeStrings();
-#endif /* __INSURE__ */
-}
-
-
-/* Clear argv allocated by pymain_decode_bytes_argv() */
-static void
-pymain_clear_bytes_argv(_PyMain *pymain, int argc)
-{
-    if (pymain->use_bytes_argv && pymain->argv != NULL) {
-        for (int i = 0; i < argc; i++) {
-            PyMem_RawFree(pymain->argv[i]);
-        }
-        PyMem_RawFree(pymain->argv);
-        pymain->argv = NULL;
+    for (int i=0; i < argc; i++) {
+        PyMem_RawFree(argv[i]);
     }
+    PyMem_RawFree(argv);
 }
 
 
 static int
-pymain_decode_bytes_argv(_PyMain *pymain)
+pymain_init_cmdline_argv(_PyMain *pymain)
 {
-    assert(pymain->argv == NULL);
+    assert(pymain->cmdline.argv == NULL);
+
+    if (!pymain->use_bytes_argv) {
+        pymain->cmdline.argv = pymain->wchar_argv;
+        return 0;
+    }
 
     /* +1 for a the NULL terminator */
     size_t size = sizeof(wchar_t*) * (pymain->argc + 1);
-    pymain->argv = (wchar_t **)PyMem_RawMalloc(size);
-    if (pymain->argv == NULL) {
+    wchar_t** argv = (wchar_t **)PyMem_RawMalloc(size);
+    if (argv == NULL) {
         pymain->err = _Py_INIT_NO_MEMORY();
         return -1;
     }
 
     for (int i = 0; i < pymain->argc; i++) {
         size_t len;
-        pymain->argv[i] = Py_DecodeLocale(pymain->bytes_argv[i], &len);
-        if (pymain->argv[i] == NULL) {
-            pymain_clear_bytes_argv(pymain, i);
+        wchar_t *arg = Py_DecodeLocale(pymain->bytes_argv[i], &len);
+        if (arg == NULL) {
+            clear_argv(i, argv);
             pymain->err = DECODE_LOCALE_ERR("command line arguments",
                                             (Py_ssize_t)len);
             return -1;
         }
+        argv[i] = arg;
     }
-    pymain->argv[pymain->argc] = NULL;
+    argv[pymain->argc] = NULL;
+
+    pymain->cmdline.argv = argv;
     return 0;
 }
 
 
 static void
-pymain_clear_pymain(_PyMain *pymain)
+pymain_clear_cmdline(_PyMain *pymain)
 {
+    /* Clear orig_argv: pymain_init_python_core() uses a borrowed pointer
+       to pymain->argv */
+    orig_argc = 0;
+    orig_argv = NULL;
+
     _Py_CommandLineDetails *cmdline = &pymain->cmdline;
     pymain_optlist_clear(&cmdline->warning_options);
     pymain_optlist_clear(&cmdline->xoptions);
     PyMem_RawFree(cmdline->command);
     cmdline->command = NULL;
+    pymain_optlist_clear(&cmdline->env_warning_options);
+
+    if (pymain->use_bytes_argv && cmdline->argv != NULL) {
+        clear_argv(pymain->argc, cmdline->argv);
+    }
+    cmdline->argv = NULL;
+}
+
 
-    PyMem_RawFree(pymain->sys_argv);
-    pymain->sys_argv = NULL;
-    pymain_optlist_clear(&pymain->env_warning_options);
-    pymain_clear_bytes_argv(pymain, pymain->argc);
+static void
+pymain_clear_configs(_PyMain *pymain)
+{
+    _PyMainInterpreterConfig_Clear(&pymain->config);
+
+    /* Clear core config with the memory allocator
+       used by pymain_read_conf() */
+    PyMemAllocatorEx old_alloc;
+    _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
 
     _PyCoreConfig_Clear(&pymain->core_config);
+
+    PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
 }
 
 
-/* Clear Python ojects */
 static void
-pymain_clear_python(_PyMain *pymain)
+pymain_free_python(_PyMain *pymain)
 {
     Py_CLEAR(pymain->main_importer_path);
-
     _PyMainInterpreterConfig_Clear(&pymain->config);
+
+#ifdef __INSURE__
+    /* Insure++ is a memory analysis tool that aids in discovering
+     * memory leaks and other memory problems.  On Python exit, the
+     * interned string dictionaries are flagged as being in use at exit
+     * (which it is).  Under normal circumstances, this is fine because
+     * the memory will be automatically reclaimed by the system.  Under
+     * memory debugging, it's a huge source of useless noise, so we
+     * trade off slower shutdown for less distraction in the memory
+     * reports.  -baw
+     */
+    _Py_ReleaseInternedUnicodeStrings();
+#endif /* __INSURE__ */
 }
 
 
 static void
-pymain_free(_PyMain *pymain)
+pymain_free_raw(_PyMain *pymain)
 {
+    _PyImport_Fini2();
+
+    /* Free global variables which cannot be freed in Py_Finalize():
+       configuration options set before Py_Initialize() which should
+       remain valid after Py_Finalize(), since
+       Py_Initialize()-Py_Finalize() can be called multiple times. */
+    _PyPathConfig_Clear(&_Py_path_config);
+
     /* Force the allocator used by pymain_read_conf() */
     PyMemAllocatorEx old_alloc;
     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
 
-    pymain_clear_python(pymain);
-    pymain_clear_pymain(pymain);
-    pymain_free_globals(pymain);
+    _PyCoreConfig_Clear(&pymain->core_config);
+    pymain_clear_cmdline(pymain);
 
     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
 }
 
 
+static void
+pymain_free(_PyMain *pymain)
+{
+    pymain_free_python(pymain);
+    pymain_free_raw(pymain);
+}
+
+
 static int
 pymain_run_main_from_importer(_PyMain *pymain)
 {
@@ -645,7 +665,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain)
     _PyOS_ResetGetOpt();
     do {
         int longindex = -1;
-        int c = _PyOS_GetOpt(pymain->argc, pymain->argv, PROGRAM_OPTS,
+        int c = _PyOS_GetOpt(pymain->argc, cmdline->argv, PROGRAM_OPTS,
                              longoptions, &longindex);
         if (c == EOF) {
             break;
@@ -791,9 +811,9 @@ pymain_parse_cmdline_impl(_PyMain *pymain)
 
     if (cmdline->command == NULL && cmdline->module == NULL
         && _PyOS_optind < pymain->argc
-        && wcscmp(pymain->argv[_PyOS_optind], L"-") != 0)
+        && wcscmp(cmdline->argv[_PyOS_optind], L"-") != 0)
     {
-        cmdline->filename = pymain->argv[_PyOS_optind];
+        cmdline->filename = cmdline->argv[_PyOS_optind];
     }
 
     pymain->run_code = (cmdline->command != NULL || cmdline->filename != NULL
@@ -947,7 +967,7 @@ pymain_init_warnoptions(_PyMain *pymain)
     if (pymain_add_warning_dev_mode(warnoptions, &pymain->core_config) < 0) {
         goto error;
     }
-    if (pymain_add_warnings_optlist(warnoptions, &pymain->env_warning_options) < 0) {
+    if (pymain_add_warnings_optlist(warnoptions, &pymain->cmdline.env_warning_options) < 0) {
         goto error;
     }
     if (pymain_add_warnings_optlist(warnoptions, &pymain->cmdline.warning_options) < 0) {
@@ -990,7 +1010,7 @@ pymain_warnings_envvar(_PyMain *pymain)
              warning != NULL;
              warning = wcstok_s(NULL, L",", &context)) {
 
-            if (pymain_optlist_append(pymain, &pymain->env_warning_options,
+            if (pymain_optlist_append(pymain, &pymain->cmdline.env_warning_options,
                                       warning) < 0) {
                 PyMem_RawFree(buf);
                 return -1;
@@ -1020,7 +1040,7 @@ pymain_warnings_envvar(_PyMain *pymain)
                 SET_DECODE_ERROR("PYTHONWARNINGS environment variable", len);
                 return -1;
             }
-            if (pymain_optlist_append(pymain, &pymain->env_warning_options,
+            if (pymain_optlist_append(pymain, &pymain->cmdline.env_warning_options,
                                       warning) < 0) {
                 PyMem_RawFree(warning);
                 return -1;
@@ -1142,7 +1162,7 @@ pymain_get_program_name(_PyMain *pymain)
 {
     if (pymain->core_config.program_name == NULL) {
         /* Use argv[0] by default */
-        pymain->core_config.program_name = pymain_wstrdup(pymain, pymain->argv[0]);
+        pymain->core_config.program_name = pymain_wstrdup(pymain, pymain->cmdline.argv[0]);
         if (pymain->core_config.program_name == NULL) {
             return -1;
         }
@@ -1170,66 +1190,102 @@ pymain_header(_PyMain *pymain)
 }
 
 
+static wchar_t**
+copy_argv(int argc, wchar_t **argv)
+{
+    assert(argc >= 0 && argv != NULL);
+    size_t size = argc * sizeof(argv[0]);
+    wchar_t **argv_copy = PyMem_RawMalloc(size);
+    for (int i=0; i < argc; i++) {
+        wchar_t* arg = _PyMem_RawWcsdup(argv[i]);
+        if (arg == NULL) {
+            clear_argv(i, argv);
+            return NULL;
+        }
+        argv_copy[i] = arg;
+    }
+    return argv_copy;
+}
+
+
 static int
-pymain_init_argv(_PyMain *pymain)
+pymain_init_core_argv(_PyMain *pymain)
 {
-    int argc = pymain->sys_argc;
-    wchar_t** argv = pymain->sys_argv;
+    _Py_CommandLineDetails *cmdline = &pymain->cmdline;
+
+    /* Copy argv to be able to modify it (to force -c/-m) */
+    int argc = pymain->argc - _PyOS_optind;
+    wchar_t **argv;
 
-    if (argc <= 0 || pymain->sys_argv == NULL) {
+    if (argc <= 0 || cmdline->argv == NULL) {
         /* Ensure at least one (empty) argument is seen */
         static wchar_t *empty_argv[1] = {L""};
-        argv = empty_argv;
         argc = 1;
+        argv = copy_argv(1, empty_argv);
+    }
+    else {
+        argv = copy_argv(argc, &cmdline->argv[_PyOS_optind]);
     }
 
-    PyObject *list = PyList_New(argc);
-    if (list == NULL) {
+    if (argv == NULL) {
+        pymain->err = _Py_INIT_NO_MEMORY();
         return -1;
     }
 
-    for (int i = 0; i < argc; i++) {
-        PyObject *v = PyUnicode_FromWideChar(argv[i], -1);
-        if (v == NULL) {
-            Py_DECREF(list);
+    wchar_t *arg0 = NULL;
+    if (cmdline->command != NULL) {
+        /* Force sys.argv[0] = '-c' */
+        arg0 = L"-c";
+    }
+    else if (cmdline->module != NULL) {
+        /* Force sys.argv[0] = '-m'*/
+        arg0 = L"-m";
+    }
+    if (arg0 != NULL) {
+        arg0 = _PyMem_RawWcsdup(arg0);
+        if (arg0 == NULL) {
+            clear_argv(argc, argv);
+            pymain->err = _Py_INIT_NO_MEMORY();
             return -1;
         }
-        PyList_SET_ITEM(list, i, v);
+        PyMem_RawFree(argv[0]);
+        argv[0] = arg0;
     }
 
-    pymain->config.argv = list;
+    pymain->core_config.argc = argc;
+    pymain->core_config.argv = argv;
     return 0;
 }
 
 
 static int
-pymain_init_sys_argv(_PyMain *pymain)
+config_init_argv(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_config)
 {
-    _Py_CommandLineDetails *cmdline = &pymain->cmdline;
+    assert(config->argv == NULL);
 
-    if (cmdline->command != NULL || cmdline->module != NULL) {
-        /* Backup _PyOS_optind */
-        _PyOS_optind--;
+    if (core_config->argc < 0) {
+        return 0;
     }
 
-    /* Copy argv to be able to modify it (to force -c/-m) */
-    pymain->sys_argc = pymain->argc - _PyOS_optind;
-    size_t size = pymain->sys_argc * sizeof(pymain->argv[0]);
-    pymain->sys_argv = PyMem_RawMalloc(size);
-    if (pymain->sys_argv == NULL) {
-        pymain->err = _Py_INIT_NO_MEMORY();
+    int argc = core_config->argc;
+    wchar_t** argv = core_config->argv;
+    assert(argc >= 1 && argv != NULL);
+
+    PyObject *list = PyList_New(argc);
+    if (list == NULL) {
         return -1;
     }
-    memcpy(pymain->sys_argv, &pymain->argv[_PyOS_optind], size);
 
-    if (cmdline->command != NULL) {
-        /* Force sys.argv[0] = '-c' */
-        pymain->sys_argv[0] = L"-c";
-    }
-    else if (cmdline->module != NULL) {
-        /* Force sys.argv[0] = '-m'*/
-        pymain->sys_argv[0] = L"-m";
+    for (int i = 0; i < argc; i++) {
+        PyObject *v = PyUnicode_FromWideChar(argv[i], -1);
+        if (v == NULL) {
+            Py_DECREF(list);
+            return -1;
+        }
+        PyList_SET_ITEM(list, i, v);
     }
+
+    config->argv = list;
     return 0;
 }
 
@@ -1254,7 +1310,7 @@ pymain_update_sys_path(_PyMain *pymain)
         return -1;
     }
 
-    PyObject *path0 = _PyPathConfig_ComputeArgv0(pymain->sys_argc, pymain->sys_argv);
+    PyObject *path0 = _PyPathConfig_ComputeArgv0(pymain->core_config.argc, pymain->core_config.argv);
     if (path0 == NULL) {
         pymain->err = _Py_INIT_NO_MEMORY();
         return -1;
@@ -1374,7 +1430,7 @@ pymain_open_filename(_PyMain *pymain)
         else
             cfilename = "<unprintable file name>";
         fprintf(stderr, "%ls: can't open file '%s': [Errno %d] %s\n",
-                pymain->argv[0], cfilename, err, strerror(err));
+                cmdline->argv[0], cfilename, err, strerror(err));
         PyMem_Free(cfilename_buffer);
         pymain->status = 2;
         return NULL;
@@ -1397,7 +1453,7 @@ pymain_open_filename(_PyMain *pymain)
             S_ISDIR(sb.st_mode)) {
         fprintf(stderr,
                 "%ls: '%ls' is a directory, cannot continue\n",
-                pymain->argv[0], cmdline->filename);
+                cmdline->argv[0], cmdline->filename);
         fclose(fp);
         pymain->status = 1;
         return NULL;
@@ -1474,11 +1530,16 @@ pymain_parse_cmdline(_PyMain *pymain)
         return -1;
     }
     if (res) {
-        pymain_usage(1, pymain->argv[0]);
+        pymain_usage(1, pymain->cmdline.argv[0]);
         pymain->status = 2;
         return 1;
     }
 
+    if (pymain->cmdline.command != NULL || pymain->cmdline.module != NULL) {
+        /* Backup _PyOS_optind */
+        _PyOS_optind--;
+    }
+
     return 0;
 }
 
@@ -1912,7 +1973,7 @@ pymain_read_conf_impl(_PyMain *pymain)
         return -1;
     }
 
-    if (pymain_init_sys_argv(pymain) < 0) {
+    if (pymain_init_core_argv(pymain) < 0) {
         return -1;
     }
 
@@ -1960,10 +2021,8 @@ pymain_read_conf(_PyMain *pymain)
             goto done;
         }
 
-        if (pymain->use_bytes_argv) {
-            if (pymain_decode_bytes_argv(pymain) < 0) {
-                goto done;
-            }
+        if (pymain_init_cmdline_argv(pymain) < 0) {
+            goto done;
         }
 
         res = pymain_read_conf_impl(pymain);
@@ -2008,7 +2067,8 @@ pymain_read_conf(_PyMain *pymain)
            pymain_read_conf_impl(). */
         Py_UTF8Mode = pymain->core_config.utf8_mode;
         Py_IgnoreEnvironmentFlag = init_ignore_env;
-        pymain_clear_pymain(pymain);
+        _PyCoreConfig_Clear(&pymain->core_config);
+        pymain_clear_cmdline(pymain);
         pymain_get_global_config(pymain);
 
         /* The encoding changed: read again the configuration
@@ -2089,6 +2149,12 @@ _PyCoreConfig_Clear(_PyCoreConfig *config)
     CLEAR(config->home);
     CLEAR(config->program_name);
 #undef CLEAR
+
+    if (config->argc >= 0) {
+        clear_argv(config->argc, config->argv);
+        config->argc = -1;
+        config->argv = NULL;
+    }
 }
 
 
@@ -2098,6 +2164,16 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
     _PyCoreConfig_Clear(config);
 
 #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR
+#define COPY_STR_ATTR(ATTR) \
+    do { \
+        if (config2->ATTR != NULL) { \
+            config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \
+            if (config->ATTR == NULL) { \
+                return -1; \
+            } \
+        } \
+    } while (0)
+
     COPY_ATTR(ignore_environment);
     COPY_ATTR(use_hash_seed);
     COPY_ATTR(hash_seed);
@@ -2112,21 +2188,21 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
     COPY_ATTR(dump_refs);
     COPY_ATTR(malloc_stats);
     COPY_ATTR(utf8_mode);
-#undef COPY_ATTR
-
-#define COPY_STR_ATTR(ATTR) \
-    do { \
-        if (config2->ATTR != NULL) { \
-            config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \
-            if (config->ATTR == NULL) { \
-                return -1; \
-            } \
-        } \
-    } while (0)
 
     COPY_STR_ATTR(module_search_path_env);
     COPY_STR_ATTR(home);
     COPY_STR_ATTR(program_name);
+
+    if (config2->argc >= 0) {
+        wchar_t **argv = copy_argv(config2->argc, config2->argv);
+        if (argv == NULL) {
+            return -1;
+        }
+        config->argv = argv;
+    }
+    COPY_ATTR(argc);
+
+#undef COPY_ATTR
 #undef COPY_STR_ATTR
     return 0;
 }
@@ -2241,13 +2317,17 @@ config_create_path_list(const wchar_t *path, wchar_t delim)
 
 
 _PyInitError
-_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, _PyCoreConfig *core_config)
+_PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *config, const _PyCoreConfig *core_config)
 {
     _PyInitError err = _PyPathConfig_Init(core_config);
     if (_Py_INIT_FAILED(err)) {
         return err;
     }
 
+    if (config_init_argv(config, core_config) < 0) {
+        return _Py_INIT_ERR("failed to create sys.argv");
+    }
+
     /* Signal handlers are installed by default */
     if (config->install_signal_handlers < 0) {
         config->install_signal_handlers = 1;
@@ -2324,10 +2404,6 @@ pymain_init_python_main(_PyMain *pymain)
         pymain->err = _Py_INIT_NO_MEMORY();
         return -1;
     }
-    if (pymain_init_argv(pymain) < 0) {
-        pymain->err = _Py_INIT_ERR("failed to create sys.argv");
-        return -1;
-    }
 
     _PyInitError err = _PyMainInterpreterConfig_Read(&pymain->config,
                                                      &pymain->core_config);
@@ -2378,9 +2454,11 @@ pymain_run_python(_PyMain *pymain)
 }
 
 
-static int
+static void
 pymain_init(_PyMain *pymain)
 {
+    memset(&pymain->cmdline, 0, sizeof(pymain->cmdline));
+
     /* 754 requires that FP exceptions run in "no stop" mode by default,
      * and until C vendors implement C99's ways to control FP exceptions,
      * Python requires non-stop mode.  Alas, some platforms enable FP
@@ -2390,23 +2468,18 @@ pymain_init(_PyMain *pymain)
     fedisableexcept(FE_OVERFLOW);
 #endif
 
-    pymain->err = _PyRuntime_Initialize();
-    if (_Py_INIT_FAILED(pymain->err)) {
-        return -1;
-    }
-
     pymain->core_config._disable_importlib = 0;
     pymain->config.install_signal_handlers = 1;
 
     pymain_get_global_config(pymain);
-    return 0;
 }
 
 
 static int
 pymain_impl(_PyMain *pymain)
 {
-    if (pymain_init(pymain) < 0) {
+    pymain->err = _PyRuntime_Initialize();
+    if (_Py_INIT_FAILED(pymain->err)) {
         return -1;
     }
 
@@ -2423,7 +2496,7 @@ pymain_impl(_PyMain *pymain)
 
     _Py_CommandLineDetails *cmdline = &pymain->cmdline;
     if (cmdline->print_help) {
-        pymain_usage(0, pymain->argv[0]);
+        pymain_usage(0, cmdline->argv[0]);
         return 0;
     }
 
@@ -2433,8 +2506,9 @@ pymain_impl(_PyMain *pymain)
         return 0;
     }
 
-    orig_argc = pymain->argc;           /* For Py_GetArgcArgv() */
-    orig_argv = pymain->argv;
+    /* For Py_GetArgcArgv(). Cleared by pymain_free(). */
+    orig_argc = pymain->argc;
+    orig_argv = cmdline->argv;
 
     res = pymain_init_python_core(pymain);
     if (res < 0) {
@@ -2446,9 +2520,9 @@ pymain_impl(_PyMain *pymain)
         return -1;
     }
 
-    pymain_run_python(pymain);
+    pymain_clear_configs(pymain);
 
-    pymain_clear_python(pymain);
+    pymain_run_python(pymain);
 
     if (Py_FinalizeEx() < 0) {
         /* Value unlikely to be confused with a non-error exit status or
@@ -2462,16 +2536,13 @@ pymain_impl(_PyMain *pymain)
 static int
 pymain_main(_PyMain *pymain)
 {
-    memset(&pymain->cmdline, 0, sizeof(pymain->cmdline));
+    pymain_init(pymain);
 
     if (pymain_impl(pymain) < 0) {
         _Py_FatalInitError(pymain->err);
     }
     pymain_free(pymain);
 
-    orig_argc = 0;
-    orig_argv = NULL;
-
     return pymain->status;
 }
 
@@ -2480,8 +2551,9 @@ int
 Py_Main(int argc, wchar_t **argv)
 {
     _PyMain pymain = _PyMain_INIT;
+    pymain.use_bytes_argv = 0;
     pymain.argc = argc;
-    pymain.argv = argv;
+    pymain.wchar_argv = argv;
 
     return pymain_main(&pymain);
 }
@@ -2491,8 +2563,8 @@ int
 _Py_UnixMain(int argc, char **argv)
 {
     _PyMain pymain = _PyMain_INIT;
-    pymain.argc = argc;
     pymain.use_bytes_argv = 1;
+    pymain.argc = argc;
     pymain.bytes_argv = argv;
 
     return pymain_main(&pymain);



More information about the Python-checkins mailing list