Fix --no-daemonize for synctl with workers (#9995)

This commit is contained in:
Richard van der Hoff 2021-05-24 14:03:30 +01:00 committed by GitHub
parent daca7b2794
commit 82eacb0e07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 70 deletions

1
changelog.d/9995.bugfix Normal file
View File

@ -0,0 +1 @@
Fix `synctl`'s `--no-daemonize` parameter to work correctly with worker processes.

102
synctl
View File

@ -24,12 +24,13 @@ import signal
import subprocess import subprocess
import sys import sys
import time import time
from typing import Iterable
import yaml import yaml
from synapse.config import find_config_files from synapse.config import find_config_files
SYNAPSE = [sys.executable, "-m", "synapse.app.homeserver"] MAIN_PROCESS = "synapse.app.homeserver"
GREEN = "\x1b[1;32m" GREEN = "\x1b[1;32m"
YELLOW = "\x1b[1;33m" YELLOW = "\x1b[1;33m"
@ -68,71 +69,37 @@ def abort(message, colour=RED, stream=sys.stderr):
sys.exit(1) sys.exit(1)
def start(configfile: str, daemonize: bool = True) -> bool: def start(pidfile: str, app: str, config_files: Iterable[str], daemonize: bool) -> bool:
"""Attempts to start synapse. """Attempts to start a synapse main or worker process.
Args: Args:
configfile: path to a yaml synapse config file pidfile: the pidfile we expect the process to create
daemonize: whether to daemonize synapse or keep it attached to the current app: the python module to run
session config_files: config files to pass to synapse
daemonize: if True, will include a --daemonize argument to synapse
Returns: Returns:
True if the process started successfully True if the process started successfully or was already running
False if there was an error starting the process False if there was an error starting the process
If deamonize is False it will only return once synapse exits.
""" """
write("Starting ...") if os.path.exists(pidfile) and pid_running(int(open(pidfile).read())):
args = SYNAPSE print(app + " already running")
return True
args = [sys.executable, "-m", app]
for c in config_files:
args += ["-c", c]
if daemonize: if daemonize:
args.extend(["--daemonize", "-c", configfile]) args.append("--daemonize")
else:
args.extend(["-c", configfile])
try: try:
subprocess.check_call(args) subprocess.check_call(args)
write("started synapse.app.homeserver(%r)" % (configfile,), colour=GREEN) write("started %s(%s)" % (app, ",".join(config_files)), colour=GREEN)
return True return True
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
write( write(
"error starting (exit code: %d); see above for logs" % e.returncode, "error starting %s(%s) (exit code: %d); see above for logs"
colour=RED, % (app, ",".join(config_files), e.returncode),
)
return False
def start_worker(app: str, configfile: str, worker_configfile: str) -> bool:
"""Attempts to start a synapse worker.
Args:
app: name of the worker's appservice
configfile: path to a yaml synapse config file
worker_configfile: path to worker specific yaml synapse file
Returns:
True if the process started successfully
False if there was an error starting the process
"""
args = [
sys.executable,
"-m",
app,
"-c",
configfile,
"-c",
worker_configfile,
"--daemonize",
]
try:
subprocess.check_call(args)
write("started %s(%r)" % (app, worker_configfile), colour=GREEN)
return True
except subprocess.CalledProcessError as e:
write(
"error starting %s(%r) (exit code: %d); see above for logs"
% (app, worker_configfile, e.returncode),
colour=RED, colour=RED,
) )
return False return False
@ -224,10 +191,11 @@ def main():
if not os.path.exists(configfile): if not os.path.exists(configfile):
write( write(
"No config file found\n" f"Config file {configfile} does not exist.\n"
"To generate a config file, run '%s -c %s --generate-config" f"To generate a config file, run:\n"
" --server-name=<server name> --report-stats=<yes/no>'\n" f" {sys.executable} -m {MAIN_PROCESS}"
% (" ".join(SYNAPSE), options.configfile), f" -c {configfile} --generate-config"
f" --server-name=<server name> --report-stats=<yes/no>\n",
stream=sys.stderr, stream=sys.stderr,
) )
sys.exit(1) sys.exit(1)
@ -323,7 +291,7 @@ def main():
has_stopped = False has_stopped = False
if start_stop_synapse: if start_stop_synapse:
if not stop(pidfile, "synapse.app.homeserver"): if not stop(pidfile, MAIN_PROCESS):
has_stopped = False has_stopped = False
if not has_stopped and action == "stop": if not has_stopped and action == "stop":
sys.exit(1) sys.exit(1)
@ -346,30 +314,24 @@ def main():
if action == "start" or action == "restart": if action == "start" or action == "restart":
error = False error = False
if start_stop_synapse: if start_stop_synapse:
# Check if synapse is already running if not start(pidfile, MAIN_PROCESS, (configfile,), options.daemonize):
if os.path.exists(pidfile) and pid_running(int(open(pidfile).read())):
abort("synapse.app.homeserver already running")
if not start(configfile, bool(options.daemonize)):
error = True error = True
for worker in workers: for worker in workers:
env = os.environ.copy() env = os.environ.copy()
# Skip starting a worker if its already running
if os.path.exists(worker.pidfile) and pid_running(
int(open(worker.pidfile).read())
):
print(worker.app + " already running")
continue
if worker.cache_factor: if worker.cache_factor:
os.environ["SYNAPSE_CACHE_FACTOR"] = str(worker.cache_factor) os.environ["SYNAPSE_CACHE_FACTOR"] = str(worker.cache_factor)
for cache_name, factor in worker.cache_factors.items(): for cache_name, factor in worker.cache_factors.items():
os.environ["SYNAPSE_CACHE_FACTOR_" + cache_name.upper()] = str(factor) os.environ["SYNAPSE_CACHE_FACTOR_" + cache_name.upper()] = str(factor)
if not start_worker(worker.app, configfile, worker.configfile): if not start(
worker.pidfile,
worker.app,
(configfile, worker.configfile),
options.daemonize,
):
error = True error = True
# Reset env back to the original # Reset env back to the original