mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	bpo-32030: Rewrite calculate_path() (#4521)
* calculate_path() rewritten in Modules/getpath.c and PC/getpathp.c
* Move global variables into a new PyPathConfig structure.
* calculate_path():
  * Split the huge calculate_path() function into subfunctions.
  * Add PyCalculatePath structure to pass data between subfunctions.
  * Document PyCalculatePath fields.
  * Move cleanup code into a new calculate_free() subfunction
  * calculate_init() now handles Py_DecodeLocale() failures properly
  * calculate_path() is now atomic: only replace PyPathConfig
    (path_config) at once on success.
* _Py_GetPythonHomeWithConfig() now returns an error on failure
* Add _Py_INIT_NO_MEMORY() helper: report a memory allocation failure
* Coding style fixes (PEP 7)
			
			
This commit is contained in:
		
							parent
							
								
									bdb8315c21
								
							
						
					
					
						commit
						0327bde9da
					
				
					 5 changed files with 970 additions and 605 deletions
				
			
		|  | @ -7,23 +7,7 @@ | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| PyAPI_FUNC(void) Py_SetProgramName(wchar_t *); |  | ||||||
| PyAPI_FUNC(wchar_t *) Py_GetProgramName(void); |  | ||||||
| 
 |  | ||||||
| PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *); |  | ||||||
| PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void); |  | ||||||
| #ifdef Py_BUILD_CORE |  | ||||||
| PyAPI_FUNC(wchar_t *) _Py_GetPythonHomeWithConfig( |  | ||||||
|     const _PyMainInterpreterConfig *config); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #ifndef Py_LIMITED_API | #ifndef Py_LIMITED_API | ||||||
| /* Only used by applications that embed the interpreter and need to
 |  | ||||||
|  * override the standard encoding determination mechanism |  | ||||||
|  */ |  | ||||||
| PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding, |  | ||||||
|                                              const char *errors); |  | ||||||
| 
 |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     const char *prefix; |     const char *prefix; | ||||||
|     const char *msg; |     const char *msg; | ||||||
|  | @ -46,9 +30,31 @@ typedef struct { | ||||||
|    Don't abort() the process on such error. */ |    Don't abort() the process on such error. */ | ||||||
| #define _Py_INIT_USER_ERR(MSG) \ | #define _Py_INIT_USER_ERR(MSG) \ | ||||||
|     (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 1} |     (_PyInitError){.prefix = _Py_INIT_GET_FUNC(), .msg = (MSG), .user_err = 1} | ||||||
|  | #define _Py_INIT_NO_MEMORY() _Py_INIT_ERR("memory allocation failed") | ||||||
| #define _Py_INIT_FAILED(err) \ | #define _Py_INIT_FAILED(err) \ | ||||||
|     (err.msg != NULL) |     (err.msg != NULL) | ||||||
| 
 | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | PyAPI_FUNC(void) Py_SetProgramName(wchar_t *); | ||||||
|  | PyAPI_FUNC(wchar_t *) Py_GetProgramName(void); | ||||||
|  | 
 | ||||||
|  | PyAPI_FUNC(void) Py_SetPythonHome(wchar_t *); | ||||||
|  | PyAPI_FUNC(wchar_t *) Py_GetPythonHome(void); | ||||||
|  | #ifdef Py_BUILD_CORE | ||||||
|  | PyAPI_FUNC(_PyInitError) _Py_GetPythonHomeWithConfig( | ||||||
|  |     const _PyMainInterpreterConfig *config, | ||||||
|  |     wchar_t **home); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #ifndef Py_LIMITED_API | ||||||
|  | /* Only used by applications that embed the interpreter and need to
 | ||||||
|  |  * override the standard encoding determination mechanism | ||||||
|  |  */ | ||||||
|  | PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding, | ||||||
|  |                                              const char *errors); | ||||||
|  | 
 | ||||||
| /* PEP 432 Multi-phase initialization API (Private while provisional!) */ | /* PEP 432 Multi-phase initialization API (Private while provisional!) */ | ||||||
| PyAPI_FUNC(_PyInitError) _Py_InitializeCore(const _PyCoreConfig *); | PyAPI_FUNC(_PyInitError) _Py_InitializeCore(const _PyCoreConfig *); | ||||||
| PyAPI_FUNC(int) _Py_IsCoreInitialized(void); | PyAPI_FUNC(int) _Py_IsCoreInitialized(void); | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -36,6 +36,16 @@ | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #define SET_DECODE_ERROR(NAME, LEN) \ | ||||||
|  |     do { \ | ||||||
|  |         if ((LEN) == (size_t)-2) { \ | ||||||
|  |             pymain->err = _Py_INIT_ERR("failed to decode " #NAME); \ | ||||||
|  |         } \ | ||||||
|  |         else { \ | ||||||
|  |             pymain->err = _Py_INIT_NO_MEMORY(); \ | ||||||
|  |         } \ | ||||||
|  |     } while (0) | ||||||
|  | 
 | ||||||
| /* For Py_GetArgcArgv(); set by main() */ | /* For Py_GetArgcArgv(); set by main() */ | ||||||
| static wchar_t **orig_argv; | static wchar_t **orig_argv; | ||||||
| static int orig_argc; | static int orig_argc; | ||||||
|  | @ -417,9 +427,6 @@ typedef struct { | ||||||
|      .env_warning_options = {0, NULL}} |      .env_warning_options = {0, NULL}} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #define INIT_NO_MEMORY() _Py_INIT_ERR("memory allocation failed") |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static void | static void | ||||||
| pymain_optlist_clear(_Py_OptList *list) | pymain_optlist_clear(_Py_OptList *list) | ||||||
| { | { | ||||||
|  | @ -510,14 +517,14 @@ pymain_wstrdup(_PyMain *pymain, wchar_t *str) | ||||||
| { | { | ||||||
|     size_t len = wcslen(str) + 1;  /* +1 for NUL character */ |     size_t len = wcslen(str) + 1;  /* +1 for NUL character */ | ||||||
|     if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { |     if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { | ||||||
|         pymain->err = INIT_NO_MEMORY(); |         pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     size_t size = len * sizeof(wchar_t); |     size_t size = len * sizeof(wchar_t); | ||||||
|     wchar_t *str2 = PyMem_RawMalloc(size); |     wchar_t *str2 = PyMem_RawMalloc(size); | ||||||
|     if (str2 == NULL) { |     if (str2 == NULL) { | ||||||
|         pymain->err = INIT_NO_MEMORY(); |         pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -538,7 +545,7 @@ pymain_optlist_append(_PyMain *pymain, _Py_OptList *list, wchar_t *str) | ||||||
|     wchar_t **options2 = (wchar_t **)PyMem_RawRealloc(list->options, size); |     wchar_t **options2 = (wchar_t **)PyMem_RawRealloc(list->options, size); | ||||||
|     if (options2 == NULL) { |     if (options2 == NULL) { | ||||||
|         PyMem_RawFree(str2); |         PyMem_RawFree(str2); | ||||||
|         pymain->err = INIT_NO_MEMORY(); |         pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|     options2[list->len] = str2; |     options2[list->len] = str2; | ||||||
|  | @ -571,7 +578,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain) | ||||||
|             size_t len = wcslen(_PyOS_optarg) + 1 + 1; |             size_t len = wcslen(_PyOS_optarg) + 1 + 1; | ||||||
|             wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len); |             wchar_t *command = PyMem_RawMalloc(sizeof(wchar_t) * len); | ||||||
|             if (command == NULL) { |             if (command == NULL) { | ||||||
|                 pymain->err = INIT_NO_MEMORY(); |                 pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|             memcpy(command, _PyOS_optarg, len * sizeof(wchar_t)); |             memcpy(command, _PyOS_optarg, len * sizeof(wchar_t)); | ||||||
|  | @ -717,7 +724,7 @@ pymain_add_xoptions(_PyMain *pymain) | ||||||
|     for (size_t i=0; i < options->len; i++) { |     for (size_t i=0; i < options->len; i++) { | ||||||
|         wchar_t *option = options->options[i]; |         wchar_t *option = options->options[i]; | ||||||
|         if (_PySys_AddXOptionWithError(option) < 0) { |         if (_PySys_AddXOptionWithError(option) < 0) { | ||||||
|             pymain->err = INIT_NO_MEMORY(); |             pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -748,11 +755,11 @@ pymain_add_warnings_options(_PyMain *pymain) | ||||||
|     PySys_ResetWarnOptions(); |     PySys_ResetWarnOptions(); | ||||||
| 
 | 
 | ||||||
|     if (pymain_add_warnings_optlist(&pymain->env_warning_options) < 0) { |     if (pymain_add_warnings_optlist(&pymain->env_warning_options) < 0) { | ||||||
|         pymain->err = INIT_NO_MEMORY(); |         pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|     if (pymain_add_warnings_optlist(&pymain->cmdline.warning_options) < 0) { |     if (pymain_add_warnings_optlist(&pymain->cmdline.warning_options) < 0) { | ||||||
|         pymain->err = INIT_NO_MEMORY(); |         pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
|  | @ -801,7 +808,7 @@ pymain_warnings_envvar(_PyMain *pymain) | ||||||
|            C89 wcstok */ |            C89 wcstok */ | ||||||
|         buf = (char *)PyMem_RawMalloc(strlen(p) + 1); |         buf = (char *)PyMem_RawMalloc(strlen(p) + 1); | ||||||
|         if (buf == NULL) { |         if (buf == NULL) { | ||||||
|             pymain->err = INIT_NO_MEMORY(); |             pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|         strcpy(buf, p); |         strcpy(buf, p); | ||||||
|  | @ -811,13 +818,7 @@ pymain_warnings_envvar(_PyMain *pymain) | ||||||
|             size_t len; |             size_t len; | ||||||
|             wchar_t *warning = Py_DecodeLocale(p, &len); |             wchar_t *warning = Py_DecodeLocale(p, &len); | ||||||
|             if (warning == NULL) { |             if (warning == NULL) { | ||||||
|                 if (len == (size_t)-2) { |                 SET_DECODE_ERROR("PYTHONWARNINGS environment variable", len); | ||||||
|                     pymain->err = _Py_INIT_ERR("failed to decode " |  | ||||||
|                                                "PYTHONWARNINGS"); |  | ||||||
|                 } |  | ||||||
|                 else { |  | ||||||
|                     pymain->err = INIT_NO_MEMORY(); |  | ||||||
|                 } |  | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|             if (pymain_optlist_append(pymain, &pymain->env_warning_options, |             if (pymain_optlist_append(pymain, &pymain->env_warning_options, | ||||||
|  | @ -902,7 +903,7 @@ pymain_get_program_name(_PyMain *pymain) | ||||||
| 
 | 
 | ||||||
|         buffer = PyMem_RawMalloc(len * sizeof(wchar_t)); |         buffer = PyMem_RawMalloc(len * sizeof(wchar_t)); | ||||||
|         if (buffer == NULL) { |         if (buffer == NULL) { | ||||||
|             pymain->err = INIT_NO_MEMORY(); |             pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -919,16 +920,9 @@ pymain_get_program_name(_PyMain *pymain) | ||||||
|             size_t len; |             size_t len; | ||||||
|             wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, &len); |             wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, &len); | ||||||
|             if (wbuf == NULL) { |             if (wbuf == NULL) { | ||||||
|                 if (len == (size_t)-2) { |                 SET_DECODE_ERROR("__PYVENV_LAUNCHER__", len); | ||||||
|                     pymain->err = _Py_INIT_ERR("failed to decode " |  | ||||||
|                                                "__PYVENV_LAUNCHER__"); |  | ||||||
|                 return -1; |                 return -1; | ||||||
|             } |             } | ||||||
|                 else { |  | ||||||
|                     pymain->err = INIT_NO_MEMORY(); |  | ||||||
|                     return -1; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             pymain->program_name = wbuf; |             pymain->program_name = wbuf; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -1403,7 +1397,7 @@ pymain_get_env_var_dup(_PyMain *pymain, wchar_t **dest, | ||||||
|             return -2; |             return -2; | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             pymain->err = INIT_NO_MEMORY(); |             pymain->err = _Py_INIT_NO_MEMORY(); | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -1421,7 +1415,7 @@ pymain_init_pythonpath(_PyMain *pymain) | ||||||
|                                      L"PYTHONPATH", "PYTHONPATH"); |                                      L"PYTHONPATH", "PYTHONPATH"); | ||||||
|     if (res < 0) { |     if (res < 0) { | ||||||
|         if (res == -2) { |         if (res == -2) { | ||||||
|             pymain->err = _Py_INIT_ERR("failed to decode PYTHONPATH"); |             SET_DECODE_ERROR("PYTHONPATH", (size_t)-2); | ||||||
|         } |         } | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  | @ -1450,7 +1444,7 @@ pymain_init_pythonhome(_PyMain *pymain) | ||||||
|                                      L"PYTHONHOME", "PYTHONHOME"); |                                      L"PYTHONHOME", "PYTHONHOME"); | ||||||
|     if (res < 0) { |     if (res < 0) { | ||||||
|         if (res == -2) { |         if (res == -2) { | ||||||
|             pymain->err = _Py_INIT_ERR("failed to decode PYTHONHOME"); |             SET_DECODE_ERROR("PYTHONHOME", (size_t)-2); | ||||||
|         } |         } | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
							
								
								
									
										547
									
								
								PC/getpathp.c
									
										
									
									
									
								
							
							
						
						
									
										547
									
								
								PC/getpathp.c
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1477,8 +1477,9 @@ Py_SetPythonHome(wchar_t *home) | ||||||
|     default_home = home; |     default_home = home; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| wchar_t * | 
 | ||||||
| _Py_GetPythonHomeWithConfig(const _PyMainInterpreterConfig *config) | _PyInitError | ||||||
|  | _Py_GetPythonHomeWithConfig(const _PyMainInterpreterConfig *config, wchar_t **homep) | ||||||
| { | { | ||||||
|     /* Use a static buffer to avoid heap memory allocation failure.
 |     /* Use a static buffer to avoid heap memory allocation failure.
 | ||||||
|        Py_GetPythonHome() doesn't allow to report error, and the caller |        Py_GetPythonHome() doesn't allow to report error, and the caller | ||||||
|  | @ -1486,32 +1487,40 @@ _Py_GetPythonHomeWithConfig(const _PyMainInterpreterConfig *config) | ||||||
|     static wchar_t buffer[MAXPATHLEN+1]; |     static wchar_t buffer[MAXPATHLEN+1]; | ||||||
| 
 | 
 | ||||||
|     if (default_home) { |     if (default_home) { | ||||||
|         return default_home; |         *homep = default_home; | ||||||
|  |         return _Py_INIT_OK(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (config) { |     if (config) { | ||||||
|         return config->pythonhome; |         *homep = config->pythonhome; | ||||||
|  |         return _Py_INIT_OK(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     char *home = Py_GETENV("PYTHONHOME"); |     char *home = Py_GETENV("PYTHONHOME"); | ||||||
|     if (!home) { |     if (!home) { | ||||||
|         return NULL; |         *homep = NULL; | ||||||
|  |         return _Py_INIT_OK(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     size_t size = Py_ARRAY_LENGTH(buffer); |     size_t size = Py_ARRAY_LENGTH(buffer); | ||||||
|     size_t r = mbstowcs(buffer, home, size); |     size_t r = mbstowcs(buffer, home, size); | ||||||
|     if (r == (size_t)-1 || r >= size) { |     if (r == (size_t)-1 || r >= size) { | ||||||
|         /* conversion failed or the static buffer is too small */ |         /* conversion failed or the static buffer is too small */ | ||||||
|         return NULL; |         *homep = NULL; | ||||||
|  |         return _Py_INIT_ERR("failed to decode PYTHONHOME environment variable"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return buffer; |     *homep = buffer; | ||||||
|  |     return _Py_INIT_OK(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| wchar_t * | wchar_t * | ||||||
| Py_GetPythonHome(void) | Py_GetPythonHome(void) | ||||||
| { | { | ||||||
|     return _Py_GetPythonHomeWithConfig(NULL); |     wchar_t *home; | ||||||
|  |     /* Ignore error */ | ||||||
|  |     (void)_Py_GetPythonHomeWithConfig(NULL, &home); | ||||||
|  |     return home; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Add the __main__ module */ | /* Add the __main__ module */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner