We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Could not load library ".../libpqwalreceiver.so"
We compile and install Postgres in a non-standard location (/opt/custom/share/postgresql-9.6.2_7 in the example below) which requires that we specify the `LD_LIBRARY_PATH` env var when starting up postgres and when working with postgres utilities. When starting up Postgres, Patroni currently passes along `PATH`, `LC_ALL` and `LANG` env vars if they are set, but does not do the same with `LD_LIBRARY_PATH`. This results in the following FATAL replication error on the replica node:
```
2018-06-05 21:10:26,675 INFO: Lock owner: postgresdb-01; I am postgresdb-02
2018-06-05 21:10:26,675 INFO: does not have lock
2018-06-05 21:10:26,676 INFO: no action.  i am a secondary and i am following a leader
FATAL:  could not load library "/opt/custom/share/postgresql-9.6.2_7/lib/libpqwalreceiver.so": libpq.so.5: cannot open shared object file: No such file or directory
FATAL:  could not load library "/opt/custom/share/postgresql-9.6.2_7/lib/libpqwalreceiver.so": libpq.so.5: cannot open shared object file: No such file or directory
```

The fix for this is to pass `LD_LIBRARY_PATH` along with the other env vars, which results in replication behaving as expected:
```
2018-06-05 22:03:08,722 INFO: Lock owner: postgresdb-01; I am postgresdb-02
2018-06-05 22:03:08,722 INFO: does not have lock
2018-06-05 22:03:08,727 DEBUG: Sending request(xid=49): SetData(path='/service/postgres_cluster/members/postgresdb-02', data='{"conn_url":"postgres://postgresdb-02:5432/postgres","api_url":"http://postgresdb-02:8008/patroni","timeline":1,"state":"running","role":"replica","xlog_location":184664496}', version=-1)
2018-06-05 22:03:08,737 DEBUG: Received response(xid=49): ZnodeStat(czxid=4294967413, mzxid=4294967497, ctime=1528235848173, mtime=1528236188727, version=28, cversion=0, aversion=0, ephemeralOwner=216194533074731009, dataLength=169, numChildren=0, pzxid=4294967413)
2018-06-05 22:03:08,741 INFO: no action.  i am a secondary and i am following a leader
```

I will submit a pull request shortly that addresses this problem.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `patroni/postmaster.py`
Content:
```
1 import logging
2 import os
3 import psutil
4 import re
5 import signal
6 import subprocess
7 
8 from patroni import call_self
9 
10 logger = logging.getLogger(__name__)
11 
12 STOP_SIGNALS = {
13     'smart': signal.SIGTERM,
14     'fast': signal.SIGINT,
15     'immediate': signal.SIGQUIT,
16 }
17 
18 
19 class PostmasterProcess(psutil.Process):
20 
21     def __init__(self, pid):
22         self.is_single_user = False
23         if pid < 0:
24             pid = -pid
25             self.is_single_user = True
26         super(PostmasterProcess, self).__init__(pid)
27 
28     @staticmethod
29     def _read_postmaster_pidfile(data_dir):
30         """Reads and parses postmaster.pid from the data directory
31 
32         :returns dictionary of values if successful, empty dictionary otherwise
33         """
34         pid_line_names = ['pid', 'data_dir', 'start_time', 'port', 'socket_dir', 'listen_addr', 'shmem_key']
35         try:
36             with open(os.path.join(data_dir, 'postmaster.pid')) as f:
37                 return {name: line.rstrip('\n') for name, line in zip(pid_line_names, f)}
38         except IOError:
39             return {}
40 
41     def _is_postmaster_process(self):
42         try:
43             start_time = int(self._postmaster_pid.get('start_time', 0))
44             if start_time and abs(self.create_time() - start_time) > 3:
45                 logger.info('Too much difference between %s and %s', self.create_time(), start_time)
46                 return False
47         except ValueError:
48             logger.warning('Garbage start time value in pid file: %r', self._postmaster_pid.get('start_time'))
49 
50         # Extra safety check. The process can't be ourselves, our parent or our direct child.
51         if self.pid == os.getpid() or self.pid == os.getppid() or self.ppid() == os.getpid():
52             logger.info('Patroni (pid=%s, ppid=%s), "fake postmaster" (pid=%s, ppid=%s)',
53                         os.getpid(), os.getppid(), self.pid, self.ppid())
54             return False
55 
56         return True
57 
58     @classmethod
59     def _from_pidfile(cls, data_dir):
60         postmaster_pid = PostmasterProcess._read_postmaster_pidfile(data_dir)
61         try:
62             pid = int(postmaster_pid.get('pid', 0))
63             if pid:
64                 proc = cls(pid)
65                 proc._postmaster_pid = postmaster_pid
66                 return proc
67         except ValueError:
68             pass
69 
70     @staticmethod
71     def from_pidfile(data_dir):
72         try:
73             proc = PostmasterProcess._from_pidfile(data_dir)
74             return proc if proc and proc._is_postmaster_process() else None
75         except psutil.NoSuchProcess:
76             return None
77 
78     @classmethod
79     def from_pid(cls, pid):
80         try:
81             return cls(pid)
82         except psutil.NoSuchProcess:
83             return None
84 
85     def signal_stop(self, mode):
86         """Signal postmaster process to stop
87 
88         :returns None if signaled, True if process is already gone, False if error
89         """
90         if self.is_single_user:
91             logger.warning("Cannot stop server; single-user server is running (PID: {0})".format(self.pid))
92             return False
93         try:
94             self.send_signal(STOP_SIGNALS[mode])
95         except psutil.NoSuchProcess:
96             return True
97         except psutil.AccessDenied as e:
98             logger.warning("Could not send stop signal to PostgreSQL (error: {0})".format(e))
99             return False
100 
101         return None
102 
103     def wait_for_user_backends_to_close(self):
104         # These regexps are cross checked against versions PostgreSQL 9.1 .. 9.6
105         aux_proc_re = re.compile("(?:postgres:)( .*:)? (?:""(?:startup|logger|checkpointer|writer|wal writer|"
106                                  "autovacuum launcher|autovacuum worker|stats collector|wal receiver|archiver|"
107                                  "wal sender) process|bgworker: )")
108 
109         try:
110             user_backends = []
111             user_backends_cmdlines = []
112             for child in self.children():
113                 try:
114                     cmdline = child.cmdline()[0]
115                     if not aux_proc_re.match(cmdline):
116                         user_backends.append(child)
117                         user_backends_cmdlines.append(cmdline)
118                 except psutil.NoSuchProcess:
119                     pass
120             if user_backends:
121                 logger.debug('Waiting for user backends %s to close', ', '.join(user_backends_cmdlines))
122                 psutil.wait_procs(user_backends)
123             logger.debug("Backends closed")
124         except psutil.Error:
125             logger.exception('wait_for_user_backends_to_close')
126 
127     @staticmethod
128     def start(pgcommand, data_dir, conf, options):
129         # Unfortunately `pg_ctl start` does not return postmaster pid to us. Without this information
130         # it is hard to know the current state of postgres startup, so we had to reimplement pg_ctl start
131         # in python. It will start postgres, wait for port to be open and wait until postgres will start
132         # accepting connections.
133         # Important!!! We can't just start postgres using subprocess.Popen, because in this case it
134         # will be our child for the rest of our live and we will have to take care of it (`waitpid`).
135         # So we will use the same approach as pg_ctl uses: start a new process, which will start postgres.
136         # This process will write postmaster pid to stdout and exit immediately. Now it's responsibility
137         # of init process to take care about postmaster.
138         # In order to make everything portable we can't use fork&exec approach here, so  we will call
139         # ourselves and pass list of arguments which must be used to start postgres.
140         env = {p: os.environ[p] for p in ('PATH', 'LC_ALL', 'LANG') if p in os.environ}
141         try:
142             proc = PostmasterProcess._from_pidfile(data_dir)
143             if proc and not proc._is_postmaster_process():
144                 # Upon start postmaster process performs various safety checks if there is a postmaster.pid
145                 # file in the data directory. Although Patroni already detected that the running process
146                 # corresponding to the postmaster.pid is not a postmaster, the new postmaster might fail
147                 # to start, because it thinks that postmaster.pid is already locked.
148                 # Important!!! Unlink of postmaster.pid isn't an option, because it has a lot of nasty race conditions.
149                 # Luckily there is a workaround to this problem, we can pass the pid from postmaster.pid
150                 # in the `PG_GRANDPARENT_PID` environment variable and postmaster will ignore it.
151                 env['PG_GRANDPARENT_PID'] = str(proc.pid)
152         except psutil.NoSuchProcess:
153             pass
154 
155         proc = call_self(['pg_ctl_start', pgcommand, '-D', data_dir,
156                           '--config-file={}'.format(conf)] + options, close_fds=True,
157                          preexec_fn=os.setsid, stdout=subprocess.PIPE, env=env)
158         pid = int(proc.stdout.readline().strip())
159         proc.wait()
160         logger.info('postmaster pid=%s', pid)
161 
162         # TODO: In an extremely unlikely case, the process could have exited and the pid reassigned. The start
163         # initiation time is not accurate enough to compare to create time as start time would also likely
164         # be relatively close. We need the subprocess extract pid+start_time in a race free manner.
165         return PostmasterProcess.from_pid(pid)
166
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/patroni/postmaster.py b/patroni/postmaster.py
--- a/patroni/postmaster.py
+++ b/patroni/postmaster.py
@@ -137,7 +137,7 @@
         # of init process to take care about postmaster.
         # In order to make everything portable we can't use fork&exec approach here, so  we will call
         # ourselves and pass list of arguments which must be used to start postgres.
-        env = {p: os.environ[p] for p in ('PATH', 'LC_ALL', 'LANG') if p in os.environ}
+        env = {p: os.environ[p] for p in ('PATH', 'LD_LIBRARY_PATH', 'LC_ALL', 'LANG') if p in os.environ}
         try:
             proc = PostmasterProcess._from_pidfile(data_dir)
             if proc and not proc._is_postmaster_process():

{"golden_diff": "diff --git a/patroni/postmaster.py b/patroni/postmaster.py\n--- a/patroni/postmaster.py\n+++ b/patroni/postmaster.py\n@@ -137,7 +137,7 @@\n         # of init process to take care about postmaster.\n         # In order to make everything portable we can't use fork&exec approach here, so  we will call\n         # ourselves and pass list of arguments which must be used to start postgres.\n-        env = {p: os.environ[p] for p in ('PATH', 'LC_ALL', 'LANG') if p in os.environ}\n+        env = {p: os.environ[p] for p in ('PATH', 'LD_LIBRARY_PATH', 'LC_ALL', 'LANG') if p in os.environ}\n         try:\n             proc = PostmasterProcess._from_pidfile(data_dir)\n             if proc and not proc._is_postmaster_process():\n", "issue": "Could not load library \".../libpqwalreceiver.so\"\nWe compile and install Postgres in a non-standard location (/opt/custom/share/postgresql-9.6.2_7 in the example below) which requires that we specify the `LD_LIBRARY_PATH` env var when starting up postgres and when working with postgres utilities. When starting up Postgres, Patroni currently passes along `PATH`, `LC_ALL` and `LANG` env vars if they are set, but does not do the same with `LD_LIBRARY_PATH`. This results in the following FATAL replication error on the replica node:\r\n```\r\n2018-06-05 21:10:26,675 INFO: Lock owner: postgresdb-01; I am postgresdb-02\r\n2018-06-05 21:10:26,675 INFO: does not have lock\r\n2018-06-05 21:10:26,676 INFO: no action.  i am a secondary and i am following a leader\r\nFATAL:  could not load library \"/opt/custom/share/postgresql-9.6.2_7/lib/libpqwalreceiver.so\": libpq.so.5: cannot open shared object file: No such file or directory\r\nFATAL:  could not load library \"/opt/custom/share/postgresql-9.6.2_7/lib/libpqwalreceiver.so\": libpq.so.5: cannot open shared object file: No such file or directory\r\n```\r\n\r\nThe fix for this is to pass `LD_LIBRARY_PATH` along with the other env vars, which results in replication behaving as expected:\r\n```\r\n2018-06-05 22:03:08,722 INFO: Lock owner: postgresdb-01; I am postgresdb-02\r\n2018-06-05 22:03:08,722 INFO: does not have lock\r\n2018-06-05 22:03:08,727 DEBUG: Sending request(xid=49): SetData(path='/service/postgres_cluster/members/postgresdb-02', data='{\"conn_url\":\"postgres://postgresdb-02:5432/postgres\",\"api_url\":\"http://postgresdb-02:8008/patroni\",\"timeline\":1,\"state\":\"running\",\"role\":\"replica\",\"xlog_location\":184664496}', version=-1)\r\n2018-06-05 22:03:08,737 DEBUG: Received response(xid=49): ZnodeStat(czxid=4294967413, mzxid=4294967497, ctime=1528235848173, mtime=1528236188727, version=28, cversion=0, aversion=0, ephemeralOwner=216194533074731009, dataLength=169, numChildren=0, pzxid=4294967413)\r\n2018-06-05 22:03:08,741 INFO: no action.  i am a secondary and i am following a leader\r\n```\r\n\r\nI will submit a pull request shortly that addresses this problem.\n", "before_files": [{"content": "import logging\nimport os\nimport psutil\nimport re\nimport signal\nimport subprocess\n\nfrom patroni import call_self\n\nlogger = logging.getLogger(__name__)\n\nSTOP_SIGNALS = {\n    'smart': signal.SIGTERM,\n    'fast': signal.SIGINT,\n    'immediate': signal.SIGQUIT,\n}\n\n\nclass PostmasterProcess(psutil.Process):\n\n    def __init__(self, pid):\n        self.is_single_user = False\n        if pid < 0:\n            pid = -pid\n            self.is_single_user = True\n        super(PostmasterProcess, self).__init__(pid)\n\n    @staticmethod\n    def _read_postmaster_pidfile(data_dir):\n        \"\"\"Reads and parses postmaster.pid from the data directory\n\n        :returns dictionary of values if successful, empty dictionary otherwise\n        \"\"\"\n        pid_line_names = ['pid', 'data_dir', 'start_time', 'port', 'socket_dir', 'listen_addr', 'shmem_key']\n        try:\n            with open(os.path.join(data_dir, 'postmaster.pid')) as f:\n                return {name: line.rstrip('\\n') for name, line in zip(pid_line_names, f)}\n        except IOError:\n            return {}\n\n    def _is_postmaster_process(self):\n        try:\n            start_time = int(self._postmaster_pid.get('start_time', 0))\n            if start_time and abs(self.create_time() - start_time) > 3:\n                logger.info('Too much difference between %s and %s', self.create_time(), start_time)\n                return False\n        except ValueError:\n            logger.warning('Garbage start time value in pid file: %r', self._postmaster_pid.get('start_time'))\n\n        # Extra safety check. The process can't be ourselves, our parent or our direct child.\n        if self.pid == os.getpid() or self.pid == os.getppid() or self.ppid() == os.getpid():\n            logger.info('Patroni (pid=%s, ppid=%s), \"fake postmaster\" (pid=%s, ppid=%s)',\n                        os.getpid(), os.getppid(), self.pid, self.ppid())\n            return False\n\n        return True\n\n    @classmethod\n    def _from_pidfile(cls, data_dir):\n        postmaster_pid = PostmasterProcess._read_postmaster_pidfile(data_dir)\n        try:\n            pid = int(postmaster_pid.get('pid', 0))\n            if pid:\n                proc = cls(pid)\n                proc._postmaster_pid = postmaster_pid\n                return proc\n        except ValueError:\n            pass\n\n    @staticmethod\n    def from_pidfile(data_dir):\n        try:\n            proc = PostmasterProcess._from_pidfile(data_dir)\n            return proc if proc and proc._is_postmaster_process() else None\n        except psutil.NoSuchProcess:\n            return None\n\n    @classmethod\n    def from_pid(cls, pid):\n        try:\n            return cls(pid)\n        except psutil.NoSuchProcess:\n            return None\n\n    def signal_stop(self, mode):\n        \"\"\"Signal postmaster process to stop\n\n        :returns None if signaled, True if process is already gone, False if error\n        \"\"\"\n        if self.is_single_user:\n            logger.warning(\"Cannot stop server; single-user server is running (PID: {0})\".format(self.pid))\n            return False\n        try:\n            self.send_signal(STOP_SIGNALS[mode])\n        except psutil.NoSuchProcess:\n            return True\n        except psutil.AccessDenied as e:\n            logger.warning(\"Could not send stop signal to PostgreSQL (error: {0})\".format(e))\n            return False\n\n        return None\n\n    def wait_for_user_backends_to_close(self):\n        # These regexps are cross checked against versions PostgreSQL 9.1 .. 9.6\n        aux_proc_re = re.compile(\"(?:postgres:)( .*:)? (?:\"\"(?:startup|logger|checkpointer|writer|wal writer|\"\n                                 \"autovacuum launcher|autovacuum worker|stats collector|wal receiver|archiver|\"\n                                 \"wal sender) process|bgworker: )\")\n\n        try:\n            user_backends = []\n            user_backends_cmdlines = []\n            for child in self.children():\n                try:\n                    cmdline = child.cmdline()[0]\n                    if not aux_proc_re.match(cmdline):\n                        user_backends.append(child)\n                        user_backends_cmdlines.append(cmdline)\n                except psutil.NoSuchProcess:\n                    pass\n            if user_backends:\n                logger.debug('Waiting for user backends %s to close', ', '.join(user_backends_cmdlines))\n                psutil.wait_procs(user_backends)\n            logger.debug(\"Backends closed\")\n        except psutil.Error:\n            logger.exception('wait_for_user_backends_to_close')\n\n    @staticmethod\n    def start(pgcommand, data_dir, conf, options):\n        # Unfortunately `pg_ctl start` does not return postmaster pid to us. Without this information\n        # it is hard to know the current state of postgres startup, so we had to reimplement pg_ctl start\n        # in python. It will start postgres, wait for port to be open and wait until postgres will start\n        # accepting connections.\n        # Important!!! We can't just start postgres using subprocess.Popen, because in this case it\n        # will be our child for the rest of our live and we will have to take care of it (`waitpid`).\n        # So we will use the same approach as pg_ctl uses: start a new process, which will start postgres.\n        # This process will write postmaster pid to stdout and exit immediately. Now it's responsibility\n        # of init process to take care about postmaster.\n        # In order to make everything portable we can't use fork&exec approach here, so  we will call\n        # ourselves and pass list of arguments which must be used to start postgres.\n        env = {p: os.environ[p] for p in ('PATH', 'LC_ALL', 'LANG') if p in os.environ}\n        try:\n            proc = PostmasterProcess._from_pidfile(data_dir)\n            if proc and not proc._is_postmaster_process():\n                # Upon start postmaster process performs various safety checks if there is a postmaster.pid\n                # file in the data directory. Although Patroni already detected that the running process\n                # corresponding to the postmaster.pid is not a postmaster, the new postmaster might fail\n                # to start, because it thinks that postmaster.pid is already locked.\n                # Important!!! Unlink of postmaster.pid isn't an option, because it has a lot of nasty race conditions.\n                # Luckily there is a workaround to this problem, we can pass the pid from postmaster.pid\n                # in the `PG_GRANDPARENT_PID` environment variable and postmaster will ignore it.\n                env['PG_GRANDPARENT_PID'] = str(proc.pid)\n        except psutil.NoSuchProcess:\n            pass\n\n        proc = call_self(['pg_ctl_start', pgcommand, '-D', data_dir,\n                          '--config-file={}'.format(conf)] + options, close_fds=True,\n                         preexec_fn=os.setsid, stdout=subprocess.PIPE, env=env)\n        pid = int(proc.stdout.readline().strip())\n        proc.wait()\n        logger.info('postmaster pid=%s', pid)\n\n        # TODO: In an extremely unlikely case, the process could have exited and the pid reassigned. The start\n        # initiation time is not accurate enough to compare to create time as start time would also likely\n        # be relatively close. We need the subprocess extract pid+start_time in a race free manner.\n        return PostmasterProcess.from_pid(pid)\n", "path": "patroni/postmaster.py"}], "after_files": [{"content": "import logging\nimport os\nimport psutil\nimport re\nimport signal\nimport subprocess\n\nfrom patroni import call_self\n\nlogger = logging.getLogger(__name__)\n\nSTOP_SIGNALS = {\n    'smart': signal.SIGTERM,\n    'fast': signal.SIGINT,\n    'immediate': signal.SIGQUIT,\n}\n\n\nclass PostmasterProcess(psutil.Process):\n\n    def __init__(self, pid):\n        self.is_single_user = False\n        if pid < 0:\n            pid = -pid\n            self.is_single_user = True\n        super(PostmasterProcess, self).__init__(pid)\n\n    @staticmethod\n    def _read_postmaster_pidfile(data_dir):\n        \"\"\"Reads and parses postmaster.pid from the data directory\n\n        :returns dictionary of values if successful, empty dictionary otherwise\n        \"\"\"\n        pid_line_names = ['pid', 'data_dir', 'start_time', 'port', 'socket_dir', 'listen_addr', 'shmem_key']\n        try:\n            with open(os.path.join(data_dir, 'postmaster.pid')) as f:\n                return {name: line.rstrip('\\n') for name, line in zip(pid_line_names, f)}\n        except IOError:\n            return {}\n\n    def _is_postmaster_process(self):\n        try:\n            start_time = int(self._postmaster_pid.get('start_time', 0))\n            if start_time and abs(self.create_time() - start_time) > 3:\n                logger.info('Too much difference between %s and %s', self.create_time(), start_time)\n                return False\n        except ValueError:\n            logger.warning('Garbage start time value in pid file: %r', self._postmaster_pid.get('start_time'))\n\n        # Extra safety check. The process can't be ourselves, our parent or our direct child.\n        if self.pid == os.getpid() or self.pid == os.getppid() or self.ppid() == os.getpid():\n            logger.info('Patroni (pid=%s, ppid=%s), \"fake postmaster\" (pid=%s, ppid=%s)',\n                        os.getpid(), os.getppid(), self.pid, self.ppid())\n            return False\n\n        return True\n\n    @classmethod\n    def _from_pidfile(cls, data_dir):\n        postmaster_pid = PostmasterProcess._read_postmaster_pidfile(data_dir)\n        try:\n            pid = int(postmaster_pid.get('pid', 0))\n            if pid:\n                proc = cls(pid)\n                proc._postmaster_pid = postmaster_pid\n                return proc\n        except ValueError:\n            pass\n\n    @staticmethod\n    def from_pidfile(data_dir):\n        try:\n            proc = PostmasterProcess._from_pidfile(data_dir)\n            return proc if proc and proc._is_postmaster_process() else None\n        except psutil.NoSuchProcess:\n            return None\n\n    @classmethod\n    def from_pid(cls, pid):\n        try:\n            return cls(pid)\n        except psutil.NoSuchProcess:\n            return None\n\n    def signal_stop(self, mode):\n        \"\"\"Signal postmaster process to stop\n\n        :returns None if signaled, True if process is already gone, False if error\n        \"\"\"\n        if self.is_single_user:\n            logger.warning(\"Cannot stop server; single-user server is running (PID: {0})\".format(self.pid))\n            return False\n        try:\n            self.send_signal(STOP_SIGNALS[mode])\n        except psutil.NoSuchProcess:\n            return True\n        except psutil.AccessDenied as e:\n            logger.warning(\"Could not send stop signal to PostgreSQL (error: {0})\".format(e))\n            return False\n\n        return None\n\n    def wait_for_user_backends_to_close(self):\n        # These regexps are cross checked against versions PostgreSQL 9.1 .. 9.6\n        aux_proc_re = re.compile(\"(?:postgres:)( .*:)? (?:\"\"(?:startup|logger|checkpointer|writer|wal writer|\"\n                                 \"autovacuum launcher|autovacuum worker|stats collector|wal receiver|archiver|\"\n                                 \"wal sender) process|bgworker: )\")\n\n        try:\n            user_backends = []\n            user_backends_cmdlines = []\n            for child in self.children():\n                try:\n                    cmdline = child.cmdline()[0]\n                    if not aux_proc_re.match(cmdline):\n                        user_backends.append(child)\n                        user_backends_cmdlines.append(cmdline)\n                except psutil.NoSuchProcess:\n                    pass\n            if user_backends:\n                logger.debug('Waiting for user backends %s to close', ', '.join(user_backends_cmdlines))\n                psutil.wait_procs(user_backends)\n            logger.debug(\"Backends closed\")\n        except psutil.Error:\n            logger.exception('wait_for_user_backends_to_close')\n\n    @staticmethod\n    def start(pgcommand, data_dir, conf, options):\n        # Unfortunately `pg_ctl start` does not return postmaster pid to us. Without this information\n        # it is hard to know the current state of postgres startup, so we had to reimplement pg_ctl start\n        # in python. It will start postgres, wait for port to be open and wait until postgres will start\n        # accepting connections.\n        # Important!!! We can't just start postgres using subprocess.Popen, because in this case it\n        # will be our child for the rest of our live and we will have to take care of it (`waitpid`).\n        # So we will use the same approach as pg_ctl uses: start a new process, which will start postgres.\n        # This process will write postmaster pid to stdout and exit immediately. Now it's responsibility\n        # of init process to take care about postmaster.\n        # In order to make everything portable we can't use fork&exec approach here, so  we will call\n        # ourselves and pass list of arguments which must be used to start postgres.\n        env = {p: os.environ[p] for p in ('PATH', 'LD_LIBRARY_PATH', 'LC_ALL', 'LANG') if p in os.environ}\n        try:\n            proc = PostmasterProcess._from_pidfile(data_dir)\n            if proc and not proc._is_postmaster_process():\n                # Upon start postmaster process performs various safety checks if there is a postmaster.pid\n                # file in the data directory. Although Patroni already detected that the running process\n                # corresponding to the postmaster.pid is not a postmaster, the new postmaster might fail\n                # to start, because it thinks that postmaster.pid is already locked.\n                # Important!!! Unlink of postmaster.pid isn't an option, because it has a lot of nasty race conditions.\n                # Luckily there is a workaround to this problem, we can pass the pid from postmaster.pid\n                # in the `PG_GRANDPARENT_PID` environment variable and postmaster will ignore it.\n                env['PG_GRANDPARENT_PID'] = str(proc.pid)\n        except psutil.NoSuchProcess:\n            pass\n\n        proc = call_self(['pg_ctl_start', pgcommand, '-D', data_dir,\n                          '--config-file={}'.format(conf)] + options, close_fds=True,\n                         preexec_fn=os.setsid, stdout=subprocess.PIPE, env=env)\n        pid = int(proc.stdout.readline().strip())\n        proc.wait()\n        logger.info('postmaster pid=%s', pid)\n\n        # TODO: In an extremely unlikely case, the process could have exited and the pid reassigned. The start\n        # initiation time is not accurate enough to compare to create time as start time would also likely\n        # be relatively close. We need the subprocess extract pid+start_time in a race free manner.\n        return PostmasterProcess.from_pid(pid)\n", "path": "patroni/postmaster.py"}]}