From 93b341c7ab968aedd926ed30cfbd3fa29be62fb3 Mon Sep 17 00:00:00 2001 From: Brett Holman Date: Fri, 5 Aug 2022 18:11:06 +0200 Subject: [PATCH 1/3] util: Fix error path and parsing in get_proc_ppid() Reference:https://github.com/canonical/cloud-init/commit/668a68fe577368555ea7f71577fc352494a98c25 Conflict:NA If IOError was thrown, the variable "contents" was unbound and threw a name error exception. Parsing /proc//stat was broken in less common cases. Fix both and add parsing tests. --- cloudinit/util.py | 10 ++++----- tests/unittests/test_util.py | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/cloudinit/util.py b/cloudinit/util.py index 0e0fc04..9e530db 100644 --- a/cloudinit/util.py +++ b/cloudinit/util.py @@ -2761,13 +2761,13 @@ def get_proc_ppid(pid): ppid = 0 try: contents = load_file("/proc/%s/stat" % pid, quiet=True) + if contents: + # see proc.5 for format + m = re.search(r"^\d+ \(.+\) [RSDZTtWXxKWP] (\d+)", str(contents)) + if m: + ppid = int(m.group(1)) except IOError as e: LOG.warning('Failed to load /proc/%s/stat. %s', pid, e) - if contents: - parts = contents.split(" ", 4) - # man proc says - # ppid %d (4) The PID of the parent. - ppid = int(parts[3]) return ppid # vi: ts=4 expandtab diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py index 1185487..3fa5059 100644 --- a/tests/unittests/test_util.py +++ b/tests/unittests/test_util.py @@ -898,6 +898,47 @@ class TestGetProcEnv(helpers.TestCase): my_ppid = os.getppid() self.assertEqual(my_ppid, util.get_proc_ppid(my_pid)) + def test_get_proc_ppid_mocked(self): + for ppid, proc_data in ( + ( + 0, + "1 (systemd) S 0 1 1 0 -1 4194560 112664 14612195 153 18014" + "274 237 756828 152754 20 0 1 0 3 173809664 3736" + "18446744073709551615 1 1 0 0 0 0 671173123 4096 1260 0 0 0 17" + "8 0 0 0 0 123974 0 0 0 0 0 0 0 0", + ), + ( + 180771, + "180781 ([pytest-xdist r) R 180771 180598 167240 34825 " + "180598 4194304 128712 7570 0 0 1061 34 8 1 20 0 2 0 6551540 " + "351993856 25173 18446744073709551615 93907896635392 " + "93907899455533 140725724279536 0 0 0 0 16781312 17642 0 0 0 " + "17 1 0 0 0 0 0 93907901810800 93907902095288 93907928788992 " + "140725724288007 140725724288074 140725724288074 " + "140725724291047 0", + ), + ( + 5620, + "8723 (Utility Process) S 5620 5191 5191 0 -1 4194304 3219 " + "0 50 0 1045 431 0 0 20 0 3 0 9007 220585984 8758 " + "18446744073709551615 94469734690816 94469735319392 " + "140728350183632 0 0 0 0 69634 1073745144 0 0 0 17 10 0 0 0 0 " + "0 94469735327152 94469735331056 94469763170304 " + "140728350189012 140728350189221 140728350189221 " + "140728350195661 0", + ), + ( + 4946, + "4947 ((sd-pam)) S 4946 4946 4946 0 -1 1077936448 54 0 0 0 " + "0 0 0 0 20 0 1 0 4136 175616000 1394 18446744073709551615 1 1" + "0 0 0 0 0 4096 0 0 0 0 17 8 0 0 0 0 0 0 0 0 0 0 0 0 0", + ), + ): + with mock.patch( + "cloudinit.util.load_file", return_value=proc_data + ): + assert ppid == util.get_proc_ppid("mocked") + class TestKernelVersion(): """test kernel version function""" -- 2.40.0