diff options
author | Victor Stinner <vstinner@redhat.com> | 2018-08-28 23:29:06 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-28 23:29:06 (GMT) |
commit | 124b9eb4e41ba1676dad954eec9a1fb3480794e4 (patch) | |
tree | 896bb0524d76ed32915e24b2320b0a8b0628ba57 /Python | |
parent | 2c8ddcf4f14f3e4c87a6fe6678ab5ad09130c6ab (diff) | |
download | cpython-124b9eb4e41ba1676dad954eec9a1fb3480794e4.zip cpython-124b9eb4e41ba1676dad954eec9a1fb3480794e4.tar.gz cpython-124b9eb4e41ba1676dad954eec9a1fb3480794e4.tar.bz2 |
bpo-34485: Add _Py_ClearStandardStreamEncoding() (GH-8982)
* Move Py_SetStandardStreamEncoding() from pylifecycle.c
to coreconfig.c
* Add _Py_ClearStandardStreamEncoding() private function.
* pymain_free() now calls _Py_ClearStandardStreamEncoding().
* Add assertions add the end of _PyCoreConfig_Read()
* _PyCoreConfig_Copy(): rename COPY_STR_ATTR() macro
to COPY_WSTR_ATTR().
* Fix get_stdio_errors() indentation.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/coreconfig.c | 118 | ||||
-rw-r--r-- | Python/pylifecycle.c | 82 |
2 files changed, 104 insertions, 96 deletions
diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 8724681..99d703c 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -85,6 +85,88 @@ _Py_wstrlist_copy(int len, wchar_t **list) } +/* Helper to allow an embedding application to override the normal + * mechanism that attempts to figure out an appropriate IO encoding + */ + +char *_Py_StandardStreamEncoding = NULL; +char *_Py_StandardStreamErrors = NULL; + +int +Py_SetStandardStreamEncoding(const char *encoding, const char *errors) +{ + if (Py_IsInitialized()) { + /* This is too late to have any effect */ + return -1; + } + + int res = 0; + + /* Py_SetStandardStreamEncoding() can be called before Py_Initialize(), + but Py_Initialize() can change the allocator. Use a known allocator + to be able to release the memory later. */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + /* Can't call PyErr_NoMemory() on errors, as Python hasn't been + * initialised yet. + * + * However, the raw memory allocators are initialised appropriately + * as C static variables, so _PyMem_RawStrdup is OK even though + * Py_Initialize hasn't been called yet. + */ + if (encoding) { + _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding); + if (!_Py_StandardStreamEncoding) { + res = -2; + goto done; + } + } + if (errors) { + _Py_StandardStreamErrors = _PyMem_RawStrdup(errors); + if (!_Py_StandardStreamErrors) { + if (_Py_StandardStreamEncoding) { + PyMem_RawFree(_Py_StandardStreamEncoding); + } + res = -3; + goto done; + } + } +#ifdef MS_WINDOWS + if (_Py_StandardStreamEncoding) { + /* Overriding the stream encoding implies legacy streams */ + Py_LegacyWindowsStdioFlag = 1; + } +#endif + +done: + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + return res; +} + + +void +_Py_ClearStandardStreamEncoding(void) +{ + /* Use the same allocator than Py_SetStandardStreamEncoding() */ + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + /* We won't need them anymore. */ + if (_Py_StandardStreamEncoding) { + PyMem_RawFree(_Py_StandardStreamEncoding); + _Py_StandardStreamEncoding = NULL; + } + if (_Py_StandardStreamErrors) { + PyMem_RawFree(_Py_StandardStreamErrors); + _Py_StandardStreamErrors = NULL; + } + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); +} + + /* Free memory allocated in config, but don't clear all attributes */ void _PyCoreConfig_Clear(_PyCoreConfig *config) @@ -134,7 +216,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) _PyCoreConfig_Clear(config); #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR -#define COPY_STR_ATTR(ATTR) \ +#define COPY_WSTR_ATTR(ATTR) \ do { \ if (config2->ATTR != NULL) { \ config->ATTR = _PyMem_RawWcsdup(config2->ATTR); \ @@ -173,25 +255,25 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_ATTR(coerce_c_locale_warn); COPY_ATTR(utf8_mode); - COPY_STR_ATTR(pycache_prefix); - COPY_STR_ATTR(module_search_path_env); - COPY_STR_ATTR(home); - COPY_STR_ATTR(program_name); - COPY_STR_ATTR(program); + COPY_WSTR_ATTR(pycache_prefix); + COPY_WSTR_ATTR(module_search_path_env); + COPY_WSTR_ATTR(home); + COPY_WSTR_ATTR(program_name); + COPY_WSTR_ATTR(program); COPY_WSTRLIST(argc, argv); COPY_WSTRLIST(nwarnoption, warnoptions); COPY_WSTRLIST(nxoption, xoptions); COPY_WSTRLIST(nmodule_search_path, module_search_paths); - COPY_STR_ATTR(executable); - COPY_STR_ATTR(prefix); - COPY_STR_ATTR(base_prefix); - COPY_STR_ATTR(exec_prefix); + COPY_WSTR_ATTR(executable); + COPY_WSTR_ATTR(prefix); + COPY_WSTR_ATTR(base_prefix); + COPY_WSTR_ATTR(exec_prefix); #ifdef MS_WINDOWS - COPY_STR_ATTR(dll_path); + COPY_WSTR_ATTR(dll_path); #endif - COPY_STR_ATTR(base_exec_prefix); + COPY_WSTR_ATTR(base_exec_prefix); COPY_ATTR(isolated); COPY_ATTR(site_import); @@ -213,7 +295,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_ATTR(_frozen); #undef COPY_ATTR -#undef COPY_STR_ATTR +#undef COPY_WSTR_ATTR #undef COPY_WSTRLIST return 0; } @@ -627,8 +709,6 @@ get_env_flag(_PyCoreConfig *config, int *flag, const char *name) static _PyInitError config_read_env_vars(_PyCoreConfig *config) { - assert(config->use_environment > 0); - /* Get environment variables */ get_env_flag(config, &config->parser_debug, "PYTHONDEBUG"); get_env_flag(config, &config->verbose, "PYTHONVERBOSE"); @@ -870,6 +950,7 @@ _PyCoreConfig_Read(_PyCoreConfig *config) _PyInitError err; _PyCoreConfig_GetGlobalConfig(config); + assert(config->use_environment >= 0); if (config->isolated > 0) { config->use_environment = 0; @@ -882,7 +963,6 @@ _PyCoreConfig_Read(_PyCoreConfig *config) } #endif - assert(config->use_environment >= 0); if (config->use_environment) { err = config_read_env_vars(config); if (_Py_INIT_FAILED(err)) { @@ -960,12 +1040,12 @@ _PyCoreConfig_Read(_PyCoreConfig *config) if (config->utf8_mode < 0) { config->utf8_mode = 0; } - if (config->_frozen < 0) { - config->_frozen = 0; - } if (config->argc < 0) { config->argc = 0; } + assert(config->coerce_c_locale >= 0); + assert(config->use_environment >= 0); + return _Py_INIT_OK(); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 4d248ed..8c77859 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -138,66 +138,6 @@ Py_IsInitialized(void) return _PyRuntime.initialized; } -/* Helper to allow an embedding application to override the normal - * mechanism that attempts to figure out an appropriate IO encoding - */ - -static char *_Py_StandardStreamEncoding = NULL; -static char *_Py_StandardStreamErrors = NULL; - -int -Py_SetStandardStreamEncoding(const char *encoding, const char *errors) -{ - if (Py_IsInitialized()) { - /* This is too late to have any effect */ - return -1; - } - - int res = 0; - - /* Py_SetStandardStreamEncoding() can be called before Py_Initialize(), - but Py_Initialize() can change the allocator. Use a known allocator - to be able to release the memory later. */ - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - /* Can't call PyErr_NoMemory() on errors, as Python hasn't been - * initialised yet. - * - * However, the raw memory allocators are initialised appropriately - * as C static variables, so _PyMem_RawStrdup is OK even though - * Py_Initialize hasn't been called yet. - */ - if (encoding) { - _Py_StandardStreamEncoding = _PyMem_RawStrdup(encoding); - if (!_Py_StandardStreamEncoding) { - res = -2; - goto done; - } - } - if (errors) { - _Py_StandardStreamErrors = _PyMem_RawStrdup(errors); - if (!_Py_StandardStreamErrors) { - if (_Py_StandardStreamEncoding) { - PyMem_RawFree(_Py_StandardStreamEncoding); - } - res = -3; - goto done; - } - } -#ifdef MS_WINDOWS - if (_Py_StandardStreamEncoding) { - /* Overriding the stream encoding implies legacy streams */ - Py_LegacyWindowsStdioFlag = 1; - } -#endif - -done: - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - return res; -} - /* Global initializations. Can be undone by Py_FinalizeEx(). Don't call this twice without an intervening Py_FinalizeEx() call. When @@ -419,9 +359,9 @@ get_stdio_errors(void) } } #endif - } + } - return "strict"; + return "strict"; } #ifdef PY_COERCE_C_LOCALE @@ -1803,6 +1743,8 @@ init_sys_streams(PyInterpreterState *interp) char *locale_encoding = NULL; char *codec_name = NULL; _PyInitError res = _Py_INIT_OK(); + extern char *_Py_StandardStreamEncoding; + extern char *_Py_StandardStreamErrors; /* Hack to avoid a nasty recursion issue when Python is invoked in verbose mode: pre-import the Latin-1 and UTF-8 codecs */ @@ -1951,22 +1893,8 @@ init_sys_streams(PyInterpreterState *interp) error: res = _Py_INIT_ERR("can't initialize sys standard streams"); - /* Use the same allocator than Py_SetStandardStreamEncoding() */ - PyMemAllocatorEx old_alloc; done: - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - /* We won't need them anymore. */ - if (_Py_StandardStreamEncoding) { - PyMem_RawFree(_Py_StandardStreamEncoding); - _Py_StandardStreamEncoding = NULL; - } - if (_Py_StandardStreamErrors) { - PyMem_RawFree(_Py_StandardStreamErrors); - _Py_StandardStreamErrors = NULL; - } - - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + _Py_ClearStandardStreamEncoding(); PyMem_RawFree(locale_encoding); PyMem_RawFree(codec_name); |