Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

synctl stop: wait for processes to exit #11459

Merged
merged 2 commits into from
Nov 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/11459.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`synctl stop` will now wait for Synapse to exit before returning.
39 changes: 14 additions & 25 deletions synctl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import signal
import subprocess
import sys
import time
from typing import Iterable
from typing import Iterable, Optional

import yaml

Expand Down Expand Up @@ -109,38 +109,36 @@ def start(pidfile: str, app: str, config_files: Iterable[str], daemonize: bool)
return False


def stop(pidfile: str, app: str) -> bool:
def stop(pidfile: str, app: str) -> Optional[int]:
"""Attempts to kill a synapse worker from the pidfile.
Args:
pidfile: path to file containing worker's pid
app: name of the worker's appservice

Returns:
True if the process stopped successfully
False if process was already stopped or an error occured
process id, or None if the process was not running
"""

if os.path.exists(pidfile):
pid = int(open(pidfile).read())
try:
os.kill(pid, signal.SIGTERM)
write("stopped %s" % (app,), colour=GREEN)
return True
return pid
except OSError as err:
if err.errno == errno.ESRCH:
write("%s not running" % (app,), colour=YELLOW)
elif err.errno == errno.EPERM:
abort("Cannot stop %s: Operation not permitted" % (app,))
else:
abort("Cannot stop %s: Unknown error" % (app,))
return False
else:
write(
"No running worker of %s found (from %s)\nThe process might be managed by another controller (e.g. systemd)"
% (app, pidfile),
colour=YELLOW,
)
return False
return None


Worker = collections.namedtuple(
Expand Down Expand Up @@ -288,32 +286,23 @@ def main():
action = options.action

if action == "stop" or action == "restart":
has_stopped = True
running_pids = []
for worker in workers:
if not stop(worker.pidfile, worker.app):
# A worker could not be stopped.
has_stopped = False
pid = stop(worker.pidfile, worker.app)
if pid is not None:
running_pids.append(pid)

if start_stop_synapse:
if not stop(pidfile, MAIN_PROCESS):
has_stopped = False
if not has_stopped and action == "stop":
sys.exit(1)
pid = stop(pidfile, MAIN_PROCESS)
if pid is not None:
running_pids.append(pid)

# Wait for synapse to actually shutdown before starting it again
if action == "restart":
running_pids = []
if start_stop_synapse and os.path.exists(pidfile):
running_pids.append(int(open(pidfile).read()))
for worker in workers:
if os.path.exists(worker.pidfile):
running_pids.append(int(open(worker.pidfile).read()))
if len(running_pids) > 0:
write("Waiting for process to exit before restarting...")
write("Waiting for processes to exit...")
for running_pid in running_pids:
while pid_running(running_pid):
time.sleep(0.2)
write("All processes exited; now restarting...")
write("All processes exited")

if action == "start" or action == "restart":
error = False
Expand Down