diff --git a/patroni/postmaster.py b/patroni/postmaster.py index 0fd068ef..8debeaaf 100644 --- a/patroni/postmaster.py +++ b/patroni/postmaster.py @@ -102,28 +102,31 @@ class PostmasterProcess(psutil.Process): return None def wait_for_user_backends_to_close(self): - # These regexps are cross checked against versions PostgreSQL 9.1 .. 9.6 - aux_proc_re = re.compile("(?:postgres:)( .*:)? (?:""(?:startup|logger|checkpointer|writer|wal writer|" - "autovacuum launcher|autovacuum worker|stats collector|wal receiver|archiver|" - "wal sender) process|bgworker: )") + # These regexps are cross checked against versions PostgreSQL 9.1 .. 11 + aux_proc_re = re.compile("(?:postgres:)( .*:)? (?:(?:archiver|startup|autovacuum launcher|autovacuum worker|" + "checkpointer|logger|stats collector|wal receiver|wal writer|writer)(?: process )?|" + "walreceiver|wal sender process|walsender|walwriter|background writer|" + "logical replication launcher|logical replication worker for|bgworker:) ") try: - user_backends = [] - user_backends_cmdlines = [] - for child in self.children(): - try: - cmdline = child.cmdline()[0] - if not aux_proc_re.match(cmdline): - user_backends.append(child) - user_backends_cmdlines.append(cmdline) - except psutil.NoSuchProcess: - pass - if user_backends: - logger.debug('Waiting for user backends %s to close', ', '.join(user_backends_cmdlines)) - psutil.wait_procs(user_backends) - logger.debug("Backends closed") + children = self.children() except psutil.Error: - logger.exception('wait_for_user_backends_to_close') + return logger.debug('Failed to get list of postmaster children') + + user_backends = [] + user_backends_cmdlines = [] + for child in children: + try: + cmdline = child.cmdline()[0] + if not aux_proc_re.match(cmdline): + user_backends.append(child) + user_backends_cmdlines.append(cmdline) + except psutil.NoSuchProcess: + pass + if user_backends: + logger.debug('Waiting for user backends %s to close', ', '.join(user_backends_cmdlines)) + psutil.wait_procs(user_backends) + logger.debug("Backends closed") @staticmethod def start(pgcommand, data_dir, conf, options): diff --git a/tests/test_postmaster.py b/tests/test_postmaster.py index 86172525..ee951c64 100644 --- a/tests/test_postmaster.py +++ b/tests/test_postmaster.py @@ -67,7 +67,7 @@ class TestPostmasterProcess(unittest.TestCase): @patch('psutil.wait_procs') def test_wait_for_user_backends_to_close(self, mock_wait): c1 = Mock() - c1.cmdline = Mock(return_value=["postgres: startup process"]) + c1.cmdline = Mock(return_value=["postgres: startup process "]) c2 = Mock() c2.cmdline = Mock(return_value=["postgres: postgres postgres [local] idle"]) c3 = Mock() @@ -77,8 +77,7 @@ class TestPostmasterProcess(unittest.TestCase): self.assertIsNone(proc.wait_for_user_backends_to_close()) mock_wait.assert_called_with([c2]) - c3.cmdline = Mock(side_effect=psutil.AccessDenied(123)) - with patch('psutil.Process.children', Mock(return_value=[c3])): + with patch('psutil.Process.children', Mock(side_effect=psutil.NoSuchProcess(123))): proc = PostmasterProcess(123) self.assertIsNone(proc.wait_for_user_backends_to_close())