diff options
author | Matthew Treinish <mtreinish@kortar.org> | 2018-01-05 15:11:17 -0500 |
---|---|---|
committer | Matthew Treinish <mtreinish@kortar.org> | 2018-01-09 10:22:45 -0500 |
commit | 55e06261aa86c87c7c059fbddc97cdbaae06e8dd (patch) | |
tree | 128033a5bd5f8030fea4618772fff6484770e3b6 /oslo_concurrency | |
parent | 844198a0414e3a49597e163596b25e8d02c386fe (diff) | |
download | oslo-concurrency-55e06261aa86c87c7c059fbddc97cdbaae06e8dd.tar.gz |
Add python_exec kwarg to processutils.execute()3.25.0
This commit adds a new kwarg to the process_utils.execute() function to
specify the python executable to use when launching python to check
prlimits. This is necessary when processutils.execute() is called from
inside an API server running with uwsgi. In this case sys.executable is
uwsgi (because uwsgi links libpython.so and is actually the interpreter)
This doesn't work with the execute() function because it assumes the
cpython interpreter CLI is used for the arguments it uses to call the
prlimits module. To workaround this and enable API servers that may run
under uwsgi to use this those applications can simply pass in an
executable to use.
Longer term it might be better to migrate the prlimits usage to call
multiprocessing instead of subprocessing python. But that would require
a more significant rewrite of both processutils and prlimit to
facilitate that.
Change-Id: I0ae60f0b4cc3700c783f6018e837358f0e053a09
Closes-Bug: #1712463
Diffstat (limited to 'oslo_concurrency')
-rw-r--r-- | oslo_concurrency/processutils.py | 7 | ||||
-rw-r--r-- | oslo_concurrency/tests/unit/test_processutils.py | 13 |
2 files changed, 19 insertions, 1 deletions
diff --git a/oslo_concurrency/processutils.py b/oslo_concurrency/processutils.py index 744c849..8479a3a 100644 --- a/oslo_concurrency/processutils.py +++ b/oslo_concurrency/processutils.py @@ -262,6 +262,10 @@ def execute(*cmd, **kwargs): :param prlimit: Set resource limits on the child process. See below for a detailed description. :type prlimit: :class:`ProcessLimits` + :param python_exec: The python executable to use for enforcing + prlimits. If this is not set it will default to use + sys.executable. + :type python_exec: string :returns: (stdout, stderr) from process execution :raises: :class:`UnknownArgumentError` on receiving unknown arguments @@ -314,6 +318,7 @@ def execute(*cmd, **kwargs): on_completion = kwargs.pop('on_completion', None) preexec_fn = kwargs.pop('preexec_fn', None) prlimit = kwargs.pop('prlimit', None) + python_exec = kwargs.pop('python_exec', sys.executable) if isinstance(check_exit_code, bool): ignore_exit_code = not check_exit_code @@ -350,7 +355,7 @@ def execute(*cmd, **kwargs): _('Process resource limits are ignored as ' 'this feature is not supported on Windows.')) else: - args = [sys.executable, '-m', 'oslo_concurrency.prlimit'] + args = [python_exec, '-m', 'oslo_concurrency.prlimit'] args.extend(prlimit.prlimit_args()) args.append('--') args.extend(cmd) diff --git a/oslo_concurrency/tests/unit/test_processutils.py b/oslo_concurrency/tests/unit/test_processutils.py index 29b4c65..29576e5 100644 --- a/oslo_concurrency/tests/unit/test_processutils.py +++ b/oslo_concurrency/tests/unit/test_processutils.py @@ -968,3 +968,16 @@ class PrlimitTestCase(test_base.BaseTestCase): stderr=mock.ANY, close_fds=mock.ANY, preexec_fn=mock.ANY, shell=mock.ANY, cwd=mock.ANY, env=mock.ANY) + + @mock.patch.object(processutils.subprocess, 'Popen') + def test_python_exec(self, sub_mock): + mock_subprocess = mock.MagicMock() + mock_subprocess.communicate.return_value = (b'', b'') + sub_mock.return_value = mock_subprocess + args = ['/a/command'] + prlimit = self.limit_address_space() + + processutils.execute(*args, prlimit=prlimit, check_exit_code=False, + python_exec='/fake_path') + python_path = sub_mock.mock_calls[0][1][0][0] + self.assertEqual('/fake_path', python_path) |