mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-25 14:53:37 +00:00
implemented stop signal using pg_ctl for non posix systems (#1342)
Using pg_ctl to send stop signal for non posix os.
This commit is contained in:
committed by
Alexander Kukushkin
parent
1c4d395d5a
commit
16fe180ed6
+2
-1
@@ -1290,7 +1290,8 @@ class Ha(object):
|
||||
data_sysid = self.state_handler.sysid
|
||||
if not self.sysid_valid(data_sysid):
|
||||
# data directory is not empty, but no valid sysid, cluster must be broken, suggest reinit
|
||||
return "data dir for the cluster is not empty, but system ID is invalid; consider doing reinitalize"
|
||||
return ("data dir for the cluster is not empty, but system ID is invalid; consider doing"
|
||||
"reinitialize")
|
||||
|
||||
if self.sysid_valid(self.cluster.initialize):
|
||||
if self.cluster.initialize != data_sysid:
|
||||
|
||||
@@ -516,7 +516,7 @@ class Postgresql(object):
|
||||
self.set_state('stopping')
|
||||
|
||||
# Send signal to postmaster to stop
|
||||
success = postmaster.signal_stop(mode)
|
||||
success = postmaster.signal_stop(mode, self.pgcommand('pg_ctl'))
|
||||
if success is not None:
|
||||
if success and on_safepoint:
|
||||
on_safepoint()
|
||||
@@ -533,11 +533,10 @@ class Postgresql(object):
|
||||
|
||||
return True, True
|
||||
|
||||
@staticmethod
|
||||
def terminate_starting_postmaster(postmaster):
|
||||
def terminate_starting_postmaster(self, postmaster):
|
||||
"""Terminates a postmaster that has not yet opened ports or possibly even written a pid file. Blocks
|
||||
until the process goes away."""
|
||||
postmaster.signal_stop('immediate')
|
||||
postmaster.signal_stop('immediate', self.pgcommand('pg_ctl'))
|
||||
postmaster.wait()
|
||||
|
||||
def _wait_for_connection_close(self, postmaster):
|
||||
|
||||
@@ -22,7 +22,7 @@ logger = logging.getLogger(__name__)
|
||||
STOP_SIGNALS = {
|
||||
'smart': signal.SIGTERM,
|
||||
'fast': signal.SIGINT,
|
||||
'immediate': signal.SIGQUIT if os.name != 'nt' else signal.SIGABRT,
|
||||
'immediate': signal.SIGQUIT,
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ class PostmasterProcess(psutil.Process):
|
||||
except psutil.NoSuchProcess:
|
||||
return None
|
||||
|
||||
def signal_stop(self, mode):
|
||||
def signal_stop(self, mode, pg_ctl='pg_ctl'):
|
||||
"""Signal postmaster process to stop
|
||||
|
||||
:returns None if signaled, True if process is already gone, False if error
|
||||
@@ -113,6 +113,8 @@ class PostmasterProcess(psutil.Process):
|
||||
if self.is_single_user:
|
||||
logger.warning("Cannot stop server; single-user server is running (PID: {0})".format(self.pid))
|
||||
return False
|
||||
if os.name != 'posix':
|
||||
return self.pg_ctl_kill(mode, pg_ctl)
|
||||
try:
|
||||
self.send_signal(STOP_SIGNALS[mode])
|
||||
except psutil.NoSuchProcess:
|
||||
@@ -123,6 +125,17 @@ class PostmasterProcess(psutil.Process):
|
||||
|
||||
return None
|
||||
|
||||
def pg_ctl_kill(self, mode, pg_ctl):
|
||||
SIGNALNAME = {"smart": "TERM", "fast": "INT", "immediate": "QUIT"}[mode]
|
||||
try:
|
||||
status = subprocess.call([pg_ctl, "kill", SIGNALNAME, str(self.pid)])
|
||||
except OSError:
|
||||
return False
|
||||
if status == 0:
|
||||
return None
|
||||
else:
|
||||
return not self.is_running()
|
||||
|
||||
def wait_for_user_backends_to_close(self):
|
||||
# These regexps are cross checked against versions PostgreSQL 9.1 .. 11
|
||||
aux_proc_re = re.compile("(?:postgres:)( .*:)? (?:(?:archiver|startup|autovacuum launcher|autovacuum worker|"
|
||||
|
||||
@@ -76,6 +76,21 @@ class TestPostmasterProcess(unittest.TestCase):
|
||||
self.assertEqual(proc.signal_stop('immediate'), True)
|
||||
self.assertEqual(proc.signal_stop('immediate'), False)
|
||||
|
||||
@patch('psutil.Process.__init__', Mock())
|
||||
@patch('patroni.postgresql.postmaster.os')
|
||||
@patch('subprocess.call', Mock(side_effect=[0, OSError, 1]))
|
||||
@patch('psutil.Process.pid', Mock(return_value=123))
|
||||
@patch('psutil.Process.is_running', Mock(return_value=False))
|
||||
def test_signal_stop_nt(self, mock_os):
|
||||
mock_os.configure_mock(name="nt")
|
||||
proc = PostmasterProcess(-123)
|
||||
self.assertEqual(proc.signal_stop('immediate'), False)
|
||||
|
||||
proc = PostmasterProcess(123)
|
||||
self.assertEqual(proc.signal_stop('immediate'), None)
|
||||
self.assertEqual(proc.signal_stop('immediate'), False)
|
||||
self.assertEqual(proc.signal_stop('immediate'), True)
|
||||
|
||||
@patch('psutil.Process.__init__', Mock())
|
||||
@patch('psutil.wait_procs')
|
||||
def test_wait_for_user_backends_to_close(self, mock_wait):
|
||||
|
||||
Reference in New Issue
Block a user