Skip to content

Commit

Permalink
Merge pull request #3333 from boegel/sanity_LD_LIBRARY_PATH
Browse files Browse the repository at this point in the history
avoid empty entries in $LD_LIBRARY_PATH and other path-like environment variables
  • Loading branch information
ocaisa authored May 8, 2020
2 parents a8d397d + 772d823 commit 018337e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 9 deletions.
39 changes: 30 additions & 9 deletions easybuild/tools/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,18 +189,39 @@ def sanitize_env():
"""
Sanitize environment.
This function undefines all $PYTHON* environment variables,
since they may affect the build/install procedure of Python packages.
This function:
cfr. https://docs.python.org/2/using/cmdline.html#environment-variables
* Filters out empty entries from environment variables like $PATH, $LD_LIBRARY_PATH, etc.
Empty entries make no sense, and can cause problems,
see for example https://github.com/easybuilders/easybuild-easyconfigs/issues/9843 .
While the $PYTHON* environment variables may be relevant/required for EasyBuild itself,
and for any non-stdlib Python packages it uses,
they are irrelevant (and potentially harmful) when installing Python packages.
* Undefines all $PYTHON* environment variables,
since they may affect the build/install procedure of Python packages.
Note that this is not an airtight protection against the Python being used in the build/install procedure
picking up non-stdlib Python packages (e.g., setuptools, vsc-base, ...), thanks to the magic of .pth files,
cfr. https://docs.python.org/2/library/site.html .
cfr. https://docs.python.org/2/using/cmdline.html#environment-variables
While the $PYTHON* environment variables may be relevant/required for EasyBuild itself,
and for any non-stdlib Python packages it uses,
they are irrelevant (and potentially harmful) when installing Python packages.
Note that this is not an airtight protection against the Python being used in the build/install procedure
picking up non-stdlib Python packages (e.g., setuptools, vsc-base, ...), thanks to the magic of .pth files,
cfr. https://docs.python.org/2/library/site.html .
"""

# remove empty entries from $*PATH variables
for key in ['CPATH', 'LD_LIBRARY_PATH', 'LIBRARY_PATH', 'LD_PRELOAD', 'PATH']:
val = os.getenv(key)
if val:
entries = val.split(os.pathsep)
if '' in entries:
_log.info("Found %d empty entries in $%s, filtering them out...", entries.count(''), key)
newval = os.pathsep.join(x for x in entries if x)
if newval:
setvar(key, newval)
else:
unset_env_vars([key], verbose=False)

# unset all $PYTHON* environment variables
keys_to_unset = [key for key in os.environ if key.startswith('PYTHON')]
unset_env_vars(keys_to_unset, verbose=False)
31 changes: 31 additions & 0 deletions test/framework/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,37 @@ def test_unset_env_vars(self):
}
self.assertEqual(res, expected)

def test_sanitize_env(self):
"""Test sanitize_env function."""

# define $*PATH variable that include empty entries, those should get filtered out
os.environ['PATH'] = '/bar::/foo:' + self.test_prefix # middle empty entry
os.environ['LD_LIBRARY_PATH'] = '/apps/slurm/default/lib:/usr/lib:' # trailing empty entry
os.environ['LIBRARY_PATH'] = self.test_prefix + ':' + os.environ['HOME'] # no empty entries here
os.environ['CPATH'] = ':' + self.test_prefix # leading empty entry
os.environ['LD_PRELOAD'] = ':::' # only empty entries (should get unset!)

# define $PYTHON* environment variables, these should be unset by sanitize_env
os.environ['PYTHONNOUSERSITE'] = '1'
os.environ['PYTHONPATH'] = self.test_prefix
os.environ['PYTHONOPTIMIZE'] = '1'

env.sanitize_env()

self.assertFalse(any(x for x in os.environ.keys() if x.startswith('PYTHON')))

expected = {
'CPATH': self.test_prefix,
'LD_LIBRARY_PATH': '/apps/slurm/default/lib:/usr/lib',
'LIBRARY_PATH': self.test_prefix + ':' + os.environ['HOME'],
'PATH': '/bar:/foo:' + self.test_prefix,
}
for key in sorted(expected):
self.assertEqual(os.getenv(key), expected[key])
self.assertEqual(os.environ[key], expected[key])

self.assertEqual(os.getenv('LD_PRELOAD'), None)


def suite():
""" returns all the testcases in this module """
Expand Down

0 comments on commit 018337e

Please sign in to comment.