Check if process' cmdline is "space separarated"
According to proc man page process arguments in /proc/{pid}/cmdline should be separated with '\0' char and that char was used in neutron.agent.linux.utils.get_cmdline_from_pid function. Recently in fullstack tests it was noticed that sometimes it may happend that those arguments are separated with space char and this caused failed test because async_process.AsyncProcess() was not able to check that process is really active. This patch adds attempt to split cmdline arguments with space in case when split with '\0' returns only 1 element. Change-Id: I35d4c0e2cf56fc3ff15cf307aaf11a8ad8489e1f Closes-Bug: #1820870
This commit is contained in:
parent
cd38b2ca7a
commit
cf13b2f0cc
|
@ -324,7 +324,20 @@ def get_cmdline_from_pid(pid):
|
|||
if not process_is_running(pid):
|
||||
return []
|
||||
with open('/proc/%s/cmdline' % pid, 'r') as f:
|
||||
return f.readline().split('\0')[:-1]
|
||||
cmdline = f.readline()
|
||||
cmdline_args = cmdline.split('\0')[:-1]
|
||||
|
||||
# NOTE(slaweq): sometimes it may happen that values in
|
||||
# /proc/{pid}/cmdline are separated by space instead of NUL char,
|
||||
# in such case we would have everything in one element of cmdline_args
|
||||
# list and it would not match to expected cmd so we need to try to
|
||||
# split it by spaces
|
||||
if len(cmdline_args) == 1:
|
||||
cmdline_args = cmdline_args[0].split(' ')
|
||||
|
||||
LOG.debug("Found cmdline %s for rocess with PID %s.",
|
||||
cmdline_args, pid)
|
||||
return cmdline_args
|
||||
|
||||
|
||||
def cmd_matches_expected(cmd, expected_cmd):
|
||||
|
|
|
@ -27,6 +27,7 @@ import oslo_i18n
|
|||
from neutron.agent.linux import utils
|
||||
from neutron.tests import base
|
||||
from neutron.tests.common import helpers
|
||||
from neutron.tests import tools
|
||||
|
||||
|
||||
_marker = object()
|
||||
|
@ -294,6 +295,43 @@ class TestKillProcess(base.BaseTestCase):
|
|||
self._test_kill_process('1', kill_signal=signal.SIGTERM)
|
||||
|
||||
|
||||
class TestGetCmdlineFromPid(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestGetCmdlineFromPid, self).setUp()
|
||||
self.pid = 34
|
||||
self.process_is_running_mock = mock.patch.object(
|
||||
utils, "process_is_running").start()
|
||||
|
||||
def _test_cmdline(self, process, expected_cmd):
|
||||
self.process_is_running_mock.return_value = True
|
||||
mock_open = self.useFixture(
|
||||
tools.OpenFixture('/proc/%s/cmdline' % self.pid, process)
|
||||
).mock_open
|
||||
cmdline = utils.get_cmdline_from_pid(self.pid)
|
||||
mock_open.assert_called_once_with('/proc/%s/cmdline' % self.pid, 'r')
|
||||
self.assertEqual(expected_cmd, cmdline)
|
||||
|
||||
def test_cmdline_separated_with_null_char(self):
|
||||
process_cmd = "python3\0test-binary\0test option\0"
|
||||
expected_cmdline = ["python3", "test-binary", "test option"]
|
||||
self._test_cmdline(process_cmd, expected_cmdline)
|
||||
|
||||
def test_cmdline_separated_with_space_char(self):
|
||||
process_cmd = "python3 test-binary test option\0"
|
||||
expected_cmdline = ["python3", "test-binary", "test", "option"]
|
||||
self._test_cmdline(process_cmd, expected_cmdline)
|
||||
|
||||
def test_no_process_running(self):
|
||||
self.process_is_running_mock.return_value = False
|
||||
mock_open = self.useFixture(
|
||||
tools.OpenFixture('/proc/%s/cmdline' % self.pid)
|
||||
).mock_open
|
||||
cmdline = utils.get_cmdline_from_pid(self.pid)
|
||||
mock_open.assert_not_called()
|
||||
self.assertEqual([], cmdline)
|
||||
|
||||
|
||||
class TestFindChildPids(base.BaseTestCase):
|
||||
|
||||
def test_returns_empty_list_for_exit_code_1(self):
|
||||
|
|
Loading…
Reference in New Issue