From 0947ac1e43a1f9b68e6ea6264bd2f5c2c728289f Mon Sep 17 00:00:00 2001 From: Alexander Kukushkin Date: Thu, 24 Oct 2019 11:23:34 +0200 Subject: [PATCH] Fix race condition in postmaster_start_time() (#1243) when it is executed not from the main thread we need to create a new cursor object. --- patroni/postgresql/__init__.py | 9 ++++++--- tests/test_postgresql.py | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/patroni/postgresql/__init__.py b/patroni/postgresql/__init__.py index ba5eb9da..ffb5c7d2 100644 --- a/patroni/postgresql/__init__.py +++ b/patroni/postgresql/__init__.py @@ -728,9 +728,12 @@ class Postgresql(object): def postmaster_start_time(self): try: - cursor = self.query("SELECT pg_catalog.to_char(pg_catalog.pg_postmaster_start_time()," - " 'YYYY-MM-DD HH24:MI:SS.MS TZ')") - return cursor.fetchone()[0] + query = "SELECT pg_catalog.to_char(pg_catalog.pg_postmaster_start_time(), 'YYYY-MM-DD HH24:MI:SS.MS TZ')" + if current_thread().ident == self.__thread_ident: + return self.query(query).fetchone()[0] + with self.connection().cursor() as cursor: + cursor.execute(query) + return cursor.fetchone()[0] except psycopg2.Error: return None diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py index b25532c4..534519d1 100644 --- a/tests/test_postgresql.py +++ b/tests/test_postgresql.py @@ -458,6 +458,10 @@ class TestPostgresql(BaseTestPostgresql): def test_postmaster_start_time(self): with patch.object(MockCursor, "fetchone", Mock(return_value=('foo', True, '', '', '', '', False))): self.assertEqual(self.p.postmaster_start_time(), 'foo') + t = Thread(target=self.p.postmaster_start_time) + t.start() + t.join() + with patch.object(MockCursor, "execute", side_effect=psycopg2.Error): self.assertIsNone(self.p.postmaster_start_time())