Skip to content

Commit

Permalink
pythonGH-126789: fix some sysconfig data on late site initializations
Browse files Browse the repository at this point in the history
Signed-off-by: Filipe Laíns <[email protected]>
  • Loading branch information
FFY00 committed Dec 7, 2024
1 parent 79b7cab commit e9d8a6d
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
18 changes: 13 additions & 5 deletions Lib/sysconfig/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,7 @@ def joinuser(*args):
_PY_VERSION = sys.version.split()[0]
_PY_VERSION_SHORT = f'{sys.version_info[0]}.{sys.version_info[1]}'
_PY_VERSION_SHORT_NO_DOT = f'{sys.version_info[0]}{sys.version_info[1]}'
_PREFIX = os.path.normpath(sys.prefix)
_BASE_PREFIX = os.path.normpath(sys.base_prefix)
_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
# Mutex guarding initialization of _CONFIG_VARS.
_CONFIG_VARS_LOCK = threading.RLock()
Expand Down Expand Up @@ -473,8 +471,8 @@ def _init_config_vars():
global _CONFIG_VARS
_CONFIG_VARS = {}

prefix = _PREFIX
exec_prefix = _EXEC_PREFIX
prefix = os.path.normpath(sys.prefix)
exec_prefix = os.path.normpath(sys.exec_prefix)
base_prefix = _BASE_PREFIX
base_exec_prefix = _BASE_EXEC_PREFIX

Expand Down Expand Up @@ -564,9 +562,19 @@ def get_config_vars(*args):
With arguments, return a list of values that result from looking up
each argument in the configuration variable dictionary.
"""
global _CONFIG_VARS_INITIALIZED

# Avoid claiming the lock once initialization is complete.
if not _CONFIG_VARS_INITIALIZED:
if _CONFIG_VARS_INITIALIZED:
# GH-126789: If sys.prefix or sys.exec_prefix were updated, invalidate the cache.
prefix = os.path.normpath(sys.prefix)
exec_prefix = os.path.normpath(sys.exec_prefix)
if _CONFIG_VARS['prefix'] != prefix or _CONFIG_VARS['exec_prefix'] != exec_prefix:
with _CONFIG_VARS_LOCK:
_CONFIG_VARS_INITIALIZED = False
_init_config_vars()
else:
# Initialize the config_vars cache.
with _CONFIG_VARS_LOCK:
# Test again with the lock held to avoid races. Note that
# we test _CONFIG_VARS here, not _CONFIG_VARS_INITIALIZED,
Expand Down
25 changes: 25 additions & 0 deletions Lib/test/test_sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ def setUp(self):
os.uname = self._get_uname
# saving the environment
self.name = os.name
self.prefix = sys.prefix
self.exec_prefix = sys.exec_prefix
self.platform = sys.platform
self.version = sys.version
self._framework = sys._framework
Expand All @@ -77,6 +79,8 @@ def tearDown(self):
else:
del os.uname
os.name = self.name
sys.prefix = self.prefix
sys.exec_prefix = self.exec_prefix
sys.platform = self.platform
sys.version = self.version
sys._framework = self._framework
Expand Down Expand Up @@ -653,6 +657,27 @@ def test_sysconfigdata_json(self):

self.assertEqual(system_config_vars, json_config_vars)

def test_sysconfig_config_vars_no_prefix_cache(self):
sys.prefix = 'prefix-AAA'
sys.exec_prefix = 'exec-prefix-AAA'

config_vars = sysconfig.get_config_vars()

self.assertEqual(config_vars['prefix'], sys.prefix)
self.assertEqual(config_vars['base'], sys.prefix)
self.assertEqual(config_vars['exec_prefix'], sys.exec_prefix)
self.assertEqual(config_vars['platbase'], sys.exec_prefix)

sys.prefix = 'prefix-BBB'
sys.exec_prefix = 'exec-prefix-BBB'

config_vars = sysconfig.get_config_vars()

self.assertEqual(config_vars['prefix'], sys.prefix)
self.assertEqual(config_vars['base'], sys.prefix)
self.assertEqual(config_vars['exec_prefix'], sys.exec_prefix)
self.assertEqual(config_vars['platbase'], sys.exec_prefix)


class MakefileTests(unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Fixed :func:`sysconfig.get_config_vars`, :func:`sysconfig.get_paths`, and
siblings, returning outdated cached data if the value of :data:`sys.prefix`
or :data:`sys.exec_prefix` changes. Overwriting :data:`sys.prefix` or
:data:`sys.exec_prefix` still is discouraged, as that might break other
parts of the code.

0 comments on commit e9d8a6d

Please sign in to comment.