From 0e8b1c8f59bd1b57d31b7d31ba82c4efa6149d0a Mon Sep 17 00:00:00 2001 From: Sofia Kopikova Date: Thu, 23 Mar 2023 13:33:46 +0300 Subject: [PATCH] Catch FileNotFoundError exception When we want to find some Postgres process in testgres psutils lib first gets list of all system processes (children() function in testgres's auxiliary_processes). Next testgres asks for process name (cmdline() function), so psutils goes to /proc/pid/ in Linux. In case any of processes listed in previous step, we get FileNotFoundError --- testgres/enums.py | 13 +++++++++---- tests/test_simple.py | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/testgres/enums.py b/testgres/enums.py index fb68f2bb..d07d8068 100644 --- a/testgres/enums.py +++ b/testgres/enums.py @@ -1,5 +1,6 @@ from enum import Enum, IntEnum from six import iteritems +from psutil import NoSuchProcess class XLogMethod(Enum): @@ -68,11 +69,15 @@ def from_process(process): ], } # yapf: disable + try: + cmdline = ''.join(process.cmdline()) + except (FileNotFoundError, ProcessLookupError, NoSuchProcess): + return ProcessType.Unknown + # we deliberately cut special words and spaces - cmdline = ''.join(process.cmdline()) \ - .replace('postgres:', '', 1) \ - .replace('bgworker:', '', 1) \ - .replace(' ', '') + cmdline = cmdline.replace('postgres:', '', 1) \ + .replace('bgworker:', '', 1) \ + .replace(' ', '') for ptype in ProcessType: if cmdline.startswith(ptype.value.replace(' ', '')): diff --git a/tests/test_simple.py b/tests/test_simple.py index 9ddf5baa..d79fa79a 100755 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -9,6 +9,7 @@ import time import six import unittest +import psutil import logging.config @@ -48,6 +49,7 @@ # NOTE: those are ugly imports from testgres import bound_ports from testgres.utils import PgVer +from testgres.node import ProcessProxy def pg_version_ge(version): @@ -965,6 +967,18 @@ def test_child_pids(self): with self.assertRaises(TestgresException): replica.source_walsender + def test_child_process_dies(self): + # test for FileNotFound exception during child_processes() function + with subprocess.Popen(["sleep", "60"]) as process: + self.assertEqual(process.poll(), None) + # collect list of processes currently running + children = psutil.Process(os.getpid()).children() + # kill a process, so received children dictionary becomes invalid + process.kill() + process.wait() + # try to handle children list -- missing processes will have ptype "ProcessType.Unknown" + [ProcessProxy(p) for p in children] + if __name__ == '__main__': if os.environ.get('ALT_CONFIG'):