Skip to content

Commit c422167

Browse files
authored
bpo-38234: Remove _PyPathConfig.dll_path (GH-16307)
The DLL path is not computed from any user configuration and cannot be configured by PyConfig. Instead, add a new _Py_dll_path global variable. Remove _PyConfig_SetPathConfig(): replaced with _PyPathConfig_Init(). Py_Initialize() now longer sets the "global path configuration", but only initialize _Py_dll_path.
1 parent b154258 commit c422167

File tree

5 files changed

+85
-95
lines changed

5 files changed

+85
-95
lines changed

Include/internal/pycore_initconfig.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ extern PyStatus _PyConfig_Copy(
149149
PyConfig *config,
150150
const PyConfig *config2);
151151
extern PyStatus _PyConfig_InitPathConfig(PyConfig *config);
152-
extern PyStatus _PyConfig_SetPathConfig(
153-
const PyConfig *config);
154152
extern void _PyConfig_Write(const PyConfig *config,
155153
_PyRuntimeState *runtime);
156154
extern PyStatus _PyConfig_SetPyArgv(

Include/internal/pycore_pathconfig.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ typedef struct _PyPathConfig {
1313
wchar_t *program_full_path;
1414
wchar_t *prefix;
1515
wchar_t *exec_prefix;
16-
#ifdef MS_WINDOWS
17-
wchar_t *dll_path;
18-
#endif
19-
/* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */
16+
/* Set by Py_SetPath(), or computed by _PyConfig_InitPathConfig() */
2017
wchar_t *module_search_path;
2118
/* Python program name */
2219
wchar_t *program_name;
@@ -38,6 +35,9 @@ typedef struct _PyPathConfig {
3835
/* Note: _PyPathConfig_INIT sets other fields to 0/NULL */
3936

4037
PyAPI_DATA(_PyPathConfig) _Py_path_config;
38+
#ifdef MS_WINDOWS
39+
PyAPI_DATA(wchar_t*) _Py_dll_path;
40+
#endif
4141

4242
extern void _PyPathConfig_ClearGlobal(void);
4343
extern PyStatus _PyPathConfig_SetGlobal(
@@ -59,6 +59,8 @@ extern int _Py_FindEnvConfigValue(
5959
extern wchar_t* _Py_GetDLLPath(void);
6060
#endif
6161

62+
extern PyStatus _PyPathConfig_Init(void);
63+
6264
#ifdef __cplusplus
6365
}
6466
#endif

PC/getpathp.c

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ typedef struct {
128128

129129
wchar_t argv0_path[MAXPATHLEN+1];
130130
wchar_t zip_path[MAXPATHLEN+1];
131+
132+
wchar_t *dll_path;
131133
} PyCalculatePath;
132134

133135

@@ -666,28 +668,36 @@ read_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix, const wchar_t *path)
666668
}
667669

668670

669-
static void
671+
static PyStatus
670672
calculate_init(PyCalculatePath *calculate,
671673
const PyConfig *config)
672674
{
673675
calculate->home = config->home;
674676
calculate->path_env = _wgetenv(L"PATH");
677+
678+
calculate->dll_path = _Py_GetDLLPath();
679+
if (calculate->dll_path == NULL) {
680+
return _PyStatus_NO_MEMORY();
681+
}
682+
683+
return _PyStatus_OK();
675684
}
676685

677686

678687
static int
679-
get_pth_filename(wchar_t *spbuffer, _PyPathConfig *pathconfig)
688+
get_pth_filename(PyCalculatePath *calculate, wchar_t *filename,
689+
const _PyPathConfig *pathconfig)
680690
{
681-
if (pathconfig->dll_path[0]) {
682-
if (!change_ext(spbuffer, pathconfig->dll_path, L"._pth") &&
683-
exists(spbuffer))
691+
if (calculate->dll_path[0]) {
692+
if (!change_ext(filename, calculate->dll_path, L"._pth") &&
693+
exists(filename))
684694
{
685695
return 1;
686696
}
687697
}
688698
if (pathconfig->program_full_path[0]) {
689-
if (!change_ext(spbuffer, pathconfig->program_full_path, L"._pth") &&
690-
exists(spbuffer))
699+
if (!change_ext(filename, pathconfig->program_full_path, L"._pth") &&
700+
exists(filename))
691701
{
692702
return 1;
693703
}
@@ -697,15 +707,16 @@ get_pth_filename(wchar_t *spbuffer, _PyPathConfig *pathconfig)
697707

698708

699709
static int
700-
calculate_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix)
710+
calculate_pth_file(PyCalculatePath *calculate, _PyPathConfig *pathconfig,
711+
wchar_t *prefix)
701712
{
702-
wchar_t spbuffer[MAXPATHLEN+1];
713+
wchar_t filename[MAXPATHLEN+1];
703714

704-
if (!get_pth_filename(spbuffer, pathconfig)) {
715+
if (!get_pth_filename(calculate, filename, pathconfig)) {
705716
return 0;
706717
}
707718

708-
return read_pth_file(pathconfig, prefix, spbuffer);
719+
return read_pth_file(pathconfig, prefix, filename);
709720
}
710721

711722

@@ -966,13 +977,6 @@ calculate_path_impl(const PyConfig *config,
966977
{
967978
PyStatus status;
968979

969-
assert(pathconfig->dll_path == NULL);
970-
971-
pathconfig->dll_path = _Py_GetDLLPath();
972-
if (pathconfig->dll_path == NULL) {
973-
return _PyStatus_NO_MEMORY();
974-
}
975-
976980
status = get_program_full_path(config, calculate, pathconfig);
977981
if (_PyStatus_EXCEPTION(status)) {
978982
return status;
@@ -986,15 +990,15 @@ calculate_path_impl(const PyConfig *config,
986990
memset(prefix, 0, sizeof(prefix));
987991

988992
/* Search for a sys.path file */
989-
if (calculate_pth_file(pathconfig, prefix)) {
993+
if (calculate_pth_file(calculate, pathconfig, prefix)) {
990994
goto done;
991995
}
992996

993997
calculate_pyvenv_file(calculate);
994998

995999
/* Calculate zip archive path from DLL or exe path */
9961000
change_ext(calculate->zip_path,
997-
pathconfig->dll_path[0] ? pathconfig->dll_path : pathconfig->program_full_path,
1001+
calculate->dll_path[0] ? calculate->dll_path : pathconfig->program_full_path,
9981002
L".zip");
9991003

10001004
calculate_home_prefix(calculate, prefix);
@@ -1023,23 +1027,23 @@ calculate_free(PyCalculatePath *calculate)
10231027
{
10241028
PyMem_RawFree(calculate->machine_path);
10251029
PyMem_RawFree(calculate->user_path);
1030+
PyMem_RawFree(calculate->dll_path);
10261031
}
10271032

10281033

10291034
PyStatus
10301035
_PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config)
10311036
{
1037+
PyStatus status;
10321038
PyCalculatePath calculate;
10331039
memset(&calculate, 0, sizeof(calculate));
10341040

1035-
calculate_init(&calculate, config);
1036-
1037-
PyStatus status = calculate_path_impl(config, &calculate, pathconfig);
1041+
status = calculate_init(&calculate, config);
10381042
if (_PyStatus_EXCEPTION(status)) {
10391043
goto done;
10401044
}
10411045

1042-
status = _PyStatus_OK();
1046+
status = calculate_path_impl(config, &calculate, pathconfig);
10431047

10441048
done:
10451049
calculate_free(&calculate);
@@ -1067,7 +1071,12 @@ _Py_CheckPython3(void)
10671071

10681072
/* If there is a python3.dll next to the python3y.dll,
10691073
assume this is a build tree; use that DLL */
1070-
wcscpy(py3path, _Py_path_config.dll_path);
1074+
if (_Py_dll_path != NULL) {
1075+
wcscpy(py3path, _Py_dll_path);
1076+
}
1077+
else {
1078+
wcscpy(py3path, L"");
1079+
}
10711080
s = wcsrchr(py3path, L'\\');
10721081
if (!s) {
10731082
s = py3path;

Python/pathconfig.c

Lines changed: 43 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ extern "C" {
1515

1616

1717
_PyPathConfig _Py_path_config = _PyPathConfig_INIT;
18+
#ifdef MS_WINDOWS
19+
wchar_t *_Py_dll_path = NULL;
20+
#endif
1821

1922

2023
static int
@@ -51,9 +54,6 @@ pathconfig_clear(_PyPathConfig *config)
5154
CLEAR(config->prefix);
5255
CLEAR(config->program_full_path);
5356
CLEAR(config->exec_prefix);
54-
#ifdef MS_WINDOWS
55-
CLEAR(config->dll_path);
56-
#endif
5757
CLEAR(config->module_search_path);
5858
CLEAR(config->home);
5959
CLEAR(config->program_name);
@@ -114,54 +114,17 @@ pathconfig_calculate(_PyPathConfig *pathconfig, const PyConfig *config)
114114
}
115115

116116

117-
PyStatus
118-
_PyPathConfig_SetGlobal(const _PyPathConfig *config)
119-
{
120-
PyStatus status;
121-
_PyPathConfig new_config = _PyPathConfig_INIT;
122-
123-
PyMemAllocatorEx old_alloc;
124-
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
125-
126-
#define COPY_ATTR(ATTR) \
127-
do { \
128-
if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \
129-
pathconfig_clear(&new_config); \
130-
status = _PyStatus_NO_MEMORY(); \
131-
goto done; \
132-
} \
133-
} while (0)
134-
135-
COPY_ATTR(program_full_path);
136-
COPY_ATTR(prefix);
137-
COPY_ATTR(exec_prefix);
138-
#ifdef MS_WINDOWS
139-
COPY_ATTR(dll_path);
140-
#endif
141-
COPY_ATTR(module_search_path);
142-
COPY_ATTR(program_name);
143-
COPY_ATTR(home);
144-
COPY_ATTR(base_executable);
145-
146-
pathconfig_clear(&_Py_path_config);
147-
/* Steal new_config strings; don't clear new_config */
148-
_Py_path_config = new_config;
149-
150-
status = _PyStatus_OK();
151-
152-
done:
153-
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
154-
return status;
155-
}
156-
157-
158117
void
159118
_PyPathConfig_ClearGlobal(void)
160119
{
161120
PyMemAllocatorEx old_alloc;
162121
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
163122

164123
pathconfig_clear(&_Py_path_config);
124+
#ifdef MS_WINDOWS
125+
PyMem_RawFree(_Py_dll_path);
126+
_Py_dll_path = NULL;
127+
#endif
165128

166129
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
167130
}
@@ -200,12 +163,36 @@ _PyWideStringList_Join(const PyWideStringList *list, wchar_t sep)
200163

201164
/* Set the global path configuration from config. */
202165
PyStatus
203-
_PyConfig_SetPathConfig(const PyConfig *config)
166+
_PyPathConfig_Init(void)
204167
{
168+
#ifdef MS_WINDOWS
169+
if (_Py_dll_path == NULL) {
170+
/* Already set: nothing to do */
171+
return _PyStatus_OK();
172+
}
173+
205174
PyMemAllocatorEx old_alloc;
206175
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
207176

177+
_Py_dll_path = _Py_GetDLLPath();
178+
179+
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
180+
181+
if (_Py_dll_path == NULL) {
182+
return _PyStatus_NO_MEMORY();
183+
}
184+
#endif
185+
return _PyStatus_OK();
186+
}
187+
188+
189+
static PyStatus
190+
pathconfig_global_init_from_config(const PyConfig *config)
191+
{
208192
PyStatus status;
193+
PyMemAllocatorEx old_alloc;
194+
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
195+
209196
_PyPathConfig pathconfig = _PyPathConfig_INIT;
210197

211198
pathconfig.module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM);
@@ -222,12 +209,6 @@ _PyConfig_SetPathConfig(const PyConfig *config)
222209
if (copy_wstr(&pathconfig.exec_prefix, config->exec_prefix) < 0) {
223210
goto no_memory;
224211
}
225-
#ifdef MS_WINDOWS
226-
pathconfig.dll_path = _Py_GetDLLPath();
227-
if (pathconfig.dll_path == NULL) {
228-
goto no_memory;
229-
}
230-
#endif
231212
if (copy_wstr(&pathconfig.program_name, config->program_name) < 0) {
232213
goto no_memory;
233214
}
@@ -238,19 +219,18 @@ _PyConfig_SetPathConfig(const PyConfig *config)
238219
goto no_memory;
239220
}
240221

241-
status = _PyPathConfig_SetGlobal(&pathconfig);
242-
if (_PyStatus_EXCEPTION(status)) {
243-
goto done;
244-
}
222+
pathconfig_clear(&_Py_path_config);
223+
/* Steal new_config strings; don't clear new_config */
224+
_Py_path_config = pathconfig;
245225

246226
status = _PyStatus_OK();
247227
goto done;
248228

249229
no_memory:
230+
pathconfig_clear(&pathconfig);
250231
status = _PyStatus_NO_MEMORY();
251232

252233
done:
253-
pathconfig_clear(&pathconfig);
254234
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
255235
return status;
256236
}
@@ -402,12 +382,17 @@ _PyConfig_InitPathConfig(PyConfig *config)
402382
static void
403383
pathconfig_global_init(void)
404384
{
385+
/* Initialize _Py_dll_path if needed */
386+
PyStatus status = _PyPathConfig_Init();
387+
if (_PyStatus_EXCEPTION(status)) {
388+
Py_ExitStatusException(status);
389+
}
390+
405391
if (_Py_path_config.module_search_path != NULL) {
406392
/* Already initialized */
407393
return;
408394
}
409395

410-
PyStatus status;
411396
PyConfig config;
412397
_PyConfig_InitCompatConfig(&config);
413398

@@ -416,7 +401,7 @@ pathconfig_global_init(void)
416401
goto error;
417402
}
418403

419-
status = _PyConfig_SetPathConfig(&config);
404+
status = pathconfig_global_init_from_config(&config);
420405
if (_PyStatus_EXCEPTION(status)) {
421406
goto error;
422407
}
@@ -450,10 +435,6 @@ Py_SetPath(const wchar_t *path)
450435
alloc_error |= (new_config.prefix == NULL);
451436
new_config.exec_prefix = _PyMem_RawWcsdup(L"");
452437
alloc_error |= (new_config.exec_prefix == NULL);
453-
#ifdef MS_WINDOWS
454-
new_config.dll_path = _Py_GetDLLPath();
455-
alloc_error |= (new_config.dll_path == NULL);
456-
#endif
457438
new_config.module_search_path = _PyMem_RawWcsdup(path);
458439
alloc_error |= (new_config.module_search_path == NULL);
459440

Python/pylifecycle.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ pyinit_core_reconfigure(_PyRuntimeState *runtime,
475475
config = &interp->config;
476476

477477
if (config->_install_importlib) {
478-
status = _PyConfig_SetPathConfig(config);
478+
status = _PyPathConfig_Init();
479479
if (_PyStatus_EXCEPTION(status)) {
480480
return status;
481481
}
@@ -646,7 +646,7 @@ pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
646646
}
647647

648648
if (config->_install_importlib) {
649-
status = _PyConfig_SetPathConfig(config);
649+
status = _PyPathConfig_Init();
650650
if (_PyStatus_EXCEPTION(status)) {
651651
return status;
652652
}

0 commit comments

Comments
 (0)