From 3afd26101b4f8a752cc3515f75a463c7361af3d0 Mon Sep 17 00:00:00 2001 From: Alexander Kukushkin Date: Fri, 2 Mar 2018 22:22:43 +0100 Subject: [PATCH] Single user mode was waiting for user input and never finish (#634) Regression was introduced in https://github.com/zalando/patroni/pull/576 --- patroni/postgresql.py | 18 +++++++++++++----- tests/test_postgresql.py | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/patroni/postgresql.py b/patroni/postgresql.py index a8722785..742e1017 100644 --- a/patroni/postgresql.py +++ b/patroni/postgresql.py @@ -1790,10 +1790,20 @@ $$""".format(name, ' '.join(options)), name, password, password) return self.single_user_mode(options=opts) == 0 or None def cancellable_subprocess_call(self, *args, **kwargs): - communicate_input = kwargs.pop('communicate_input', None) for s in ('stdin', 'stdout', 'stderr'): kwargs.pop(s, None) + communicate_input = 'communicate_input' in kwargs + if communicate_input: + input_data = kwargs.pop('communicate_input', None) + if not isinstance(input_data, string_types): + input_data = '' + if input_data and input_data[-1] != '\n': + input_data += '\n' + kwargs['stdin'] = subprocess.PIPE + kwargs['stdout'] = open(os.devnull, 'w') + kwargs['stderr'] = subprocess.STDOUT + try: with self._cancellable_lock: if self._is_cancelled: @@ -1803,10 +1813,8 @@ $$""".format(name, ' '.join(options)), name, password, password) self._cancellable = subprocess.Popen(*args, **kwargs) if communicate_input: - kwargs['stdin'] = subprocess.PIPE - if communicate_input[-1] != '\n': - communicate_input += '\n' - self._cancellable.communicate(communicate_input + '\n') + if input_data: + self._cancellable.communicate(input_data) self._cancellable.stdin.close() return self._cancellable.wait() diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py index acca895c..e6d5a079 100644 --- a/tests/test_postgresql.py +++ b/tests/test_postgresql.py @@ -946,7 +946,7 @@ class TestPostgresql(unittest.TestCase): def test_cancellable_subprocess_call(self): self.p.cancel() - self.assertRaises(PostgresException, self.p.cancellable_subprocess_call) + self.assertRaises(PostgresException, self.p.cancellable_subprocess_call, communicate_input=None) @patch('patroni.postgresql.polling_loop', Mock(return_value=[0, 0])) def test_cancel(self):