From bebf9a03193644e1d96df942be7e17665ce62c1a Mon Sep 17 00:00:00 2001 From: Daniel Mitterdorfer Date: Mon, 13 Jan 2020 07:35:39 +0100 Subject: [PATCH] Detach Elasticsearch on startup (#859) With this commit we detach Elasticsearch on startup from its controlling process via the [setpgrp](http://man7.org/linux/man-pages/man3/setpgrp.3p.html) system call. Although we start Elasticsearch with the `-d` flag, this is necessary to ensure it does not receive signals like `SIGHUP` from its original parent process (Rally). --- esrally/mechanic/launcher.py | 2 +- esrally/utils/process.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/esrally/mechanic/launcher.py b/esrally/mechanic/launcher.py index 99f568af3..a8aed7c1d 100644 --- a/esrally/mechanic/launcher.py +++ b/esrally/mechanic/launcher.py @@ -194,7 +194,7 @@ def _start_process(binary_path, env): os.chdir(binary_path) cmd = [io.escape_path(os.path.join(".", "bin", "elasticsearch"))] cmd.extend(["-d", "-p", "pid"]) - ret = process.run_subprocess_with_logging(command_line=" ".join(cmd), env=env) + ret = process.run_subprocess_with_logging(command_line=" ".join(cmd), env=env, detach=True) if ret != 0: msg = "Daemon startup failed with exit code [{}]".format(ret) logging.error(msg) diff --git a/esrally/utils/process.py b/esrally/utils/process.py index efe99fbe4..8c0b0d1ee 100644 --- a/esrally/utils/process.py +++ b/esrally/utils/process.py @@ -60,7 +60,7 @@ def exit_status_as_bool(runnable, quiet=False): return False -def run_subprocess_with_logging(command_line, header=None, level=logging.INFO, env=None): +def run_subprocess_with_logging(command_line, header=None, level=logging.INFO, env=None, detach=False): """ Runs the provided command line in a subprocess. All output will be captured by a logger. @@ -68,14 +68,21 @@ def run_subprocess_with_logging(command_line, header=None, level=logging.INFO, e :param header: An optional header line that should be logged (this will be logged on info level, regardless of the defined log level). :param level: The log level to use for output (default: logging.INFO). :param env: Use specific environment variables (default: None). + :param detach: Whether to detach this process from its parent process (default: False). :return: The process exit code as an int. """ logger = logging.getLogger(__name__) logger.debug("Running subprocess [%s] with logging.", command_line) command_line_args = shlex.split(command_line) + pre_exec = os.setpgrp if detach else None if header is not None: logger.info(header) - with subprocess.Popen(command_line_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env) as command_line_process: + # pylint: disable=subprocess-popen-preexec-fn + with subprocess.Popen(command_line_args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=env, + preexec_fn=pre_exec) as command_line_process: has_output = True while has_output: line = command_line_process.stdout.readline()