pmb.helpers.run_core: change kill_as_root to sudo (MR 1997)

Replace the "kill_as_root" argument with a much simpler "sudo" argument
and remove the now obsolete check for the output mode of "kill_as_root".

"kill_as_root" would only get set to True if both conditions are met:
a) command is running with sudo
b) command is running with an output mode ("log" or "stdout") where
   pmb.helpers.run_core would kill it if it does not output anything
   before a timeout is reached

The new "sudo" argument just indicates if the command is running with
sudo (a), regardless of the output mode (b).
This commit is contained in:
Johannes Marbach 2020-12-09 19:41:12 +01:00
parent 27127f1cae
commit 8842a7d5c0
No known key found for this signature in database
GPG key ID: 5AE7F5513E0885CB
5 changed files with 23 additions and 43 deletions

View file

@ -71,6 +71,5 @@ def root(args, cmd, suffix="native", working_dir="/", output="log",
pmb.helpers.run.flat_cmd(cmd, working_dir)] pmb.helpers.run.flat_cmd(cmd, working_dir)]
cmd_sudo = ["sudo", "env", "-i", executables["sh"], "-c", cmd_sudo = ["sudo", "env", "-i", executables["sh"], "-c",
pmb.helpers.run.flat_cmd(cmd_chroot, env=env_all)] pmb.helpers.run.flat_cmd(cmd_chroot, env=env_all)]
kill_as_root = output in ["log", "stdout"]
return pmb.helpers.run_core.core(args, msg, cmd_sudo, None, output, return pmb.helpers.run_core.core(args, msg, cmd_sudo, None, output,
output_return, check, kill_as_root, disable_timeout) output_return, check, True, disable_timeout)

View file

@ -107,12 +107,6 @@ is_interactive = sys.stdout.isatty() and \
sys.stdin.isatty() sys.stdin.isatty()
# pmbootstrap will kill programs which do not output anything for several
# minutes and have one of the following output types. See
# pmb.helpers.run_core.core() for more information.
run_outputs_with_timeout = ["log", "stdout"]
# #
# CHROOT # CHROOT
# #

View file

@ -34,7 +34,7 @@ def flat_cmd(cmd, working_dir=None, env={}):
def user(args, cmd, working_dir=None, output="log", output_return=False, def user(args, cmd, working_dir=None, output="log", output_return=False,
check=None, env={}, kill_as_root=False): check=None, env={}, sudo=False):
""" """
Run a command on the host system as user. Run a command on the host system as user.
@ -56,7 +56,7 @@ def user(args, cmd, working_dir=None, output="log", output_return=False,
if env: if env:
cmd = ["sh", "-c", flat_cmd(cmd, env=env)] cmd = ["sh", "-c", flat_cmd(cmd, env=env)]
return pmb.helpers.run_core.core(args, msg, cmd, working_dir, output, return pmb.helpers.run_core.core(args, msg, cmd, working_dir, output,
output_return, check, kill_as_root) output_return, check, sudo)
def root(args, cmd, working_dir=None, output="log", output_return=False, def root(args, cmd, working_dir=None, output="log", output_return=False,
@ -74,8 +74,5 @@ def root(args, cmd, working_dir=None, output="log", output_return=False,
cmd = ["sh", "-c", flat_cmd(cmd, env=env)] cmd = ["sh", "-c", flat_cmd(cmd, env=env)]
cmd = ["sudo"] + cmd cmd = ["sudo"] + cmd
# pmbootstrap shall use 'sudo kill' to get rid of timed out programs
kill_as_root = output in pmb.config.run_outputs_with_timeout or None
return user(args, cmd, working_dir, output, output_return, check, env, return user(args, cmd, working_dir, output, output_return, check, env,
kill_as_root) True)

View file

@ -14,8 +14,7 @@ import pmb.helpers.run
called by core(). """ called by core(). """
def sanity_checks(output="log", output_return=False, check=None, def sanity_checks(output="log", output_return=False, check=None):
kill_as_root=False):
""" """
Raise an exception if the parameters passed to core() don't make sense Raise an exception if the parameters passed to core() don't make sense
(all parameters are described in core() below). (all parameters are described in core() below).
@ -33,9 +32,6 @@ def sanity_checks(output="log", output_return=False, check=None,
if output_return and output in ["tui", "background"]: if output_return and output in ["tui", "background"]:
raise RuntimeError("Can't use output_return with output: " + output) raise RuntimeError("Can't use output_return with output: " + output)
if kill_as_root and output not in pmb.config.run_outputs_with_timeout:
raise RuntimeError("Can't use kill_as_root with output: " + output)
def background(args, cmd, working_dir=None): def background(args, cmd, working_dir=None):
""" Run a subprocess in background and redirect its output to the log. """ """ Run a subprocess in background and redirect its output to the log. """
@ -85,15 +81,15 @@ def pipe_read(args, process, output_to_stdout=False, output_return=False,
return return
def kill_process_tree(args, pid, ppids, kill_as_root): def kill_process_tree(args, pid, ppids, sudo):
""" """
Recursively kill a pid and its child processes Recursively kill a pid and its child processes
:param pid: process id that will be killed :param pid: process id that will be killed
:param ppids: list of process id and parent process id tuples (pid, ppid) :param ppids: list of process id and parent process id tuples (pid, ppid)
:param kill_as_root: use sudo to kill the process :param sudo: use sudo to kill the process
""" """
if kill_as_root: if sudo:
pmb.helpers.run.root(args, ["kill", "-9", str(pid)], pmb.helpers.run.root(args, ["kill", "-9", str(pid)],
check=False) check=False)
else: else:
@ -102,15 +98,15 @@ def kill_process_tree(args, pid, ppids, kill_as_root):
for (child_pid, child_ppid) in ppids: for (child_pid, child_ppid) in ppids:
if child_ppid == str(pid): if child_ppid == str(pid):
kill_process_tree(args, child_pid, ppids, kill_as_root) kill_process_tree(args, child_pid, ppids, sudo)
def kill_command(args, pid, kill_as_root): def kill_command(args, pid, sudo):
""" """
Kill a command process and recursively kill its child processes Kill a command process and recursively kill its child processes
:param pid: process id that will be killed :param pid: process id that will be killed
:param kill_as_root: use sudo to kill the process :param sudo: use sudo to kill the process
""" """
cmd = ["ps", "-e", "-o", "pid=,ppid=", "--noheaders"] cmd = ["ps", "-e", "-o", "pid=,ppid=", "--noheaders"]
ret = subprocess.run(cmd, check=True, stdout=subprocess.PIPE) ret = subprocess.run(cmd, check=True, stdout=subprocess.PIPE)
@ -122,12 +118,12 @@ def kill_command(args, pid, kill_as_root):
raise RuntimeError("Unexpected ps output: " + row) raise RuntimeError("Unexpected ps output: " + row)
ppids.append(items) ppids.append(items)
kill_process_tree(args, pid, ppids, kill_as_root) kill_process_tree(args, pid, ppids, sudo)
def foreground_pipe(args, cmd, working_dir=None, output_to_stdout=False, def foreground_pipe(args, cmd, working_dir=None, output_to_stdout=False,
output_return=False, output_timeout=True, output_return=False, output_timeout=True,
kill_as_root=False): sudo=False):
""" """
Run a subprocess in foreground with redirected output and optionally kill Run a subprocess in foreground with redirected output and optionally kill
it after being silent for too long. it after being silent for too long.
@ -139,7 +135,7 @@ def foreground_pipe(args, cmd, working_dir=None, output_to_stdout=False,
:param output_timeout: kill the process when it doesn't print any output :param output_timeout: kill the process when it doesn't print any output
after a certain time (configured with --timeout) after a certain time (configured with --timeout)
and raise a RuntimeError exception and raise a RuntimeError exception
:param kill_as_root: use sudo to kill the process when it hits the timeout :param sudo: use sudo to kill the process when it hits the timeout
:returns: (code, output) :returns: (code, output)
* code: return code of the program * code: return code of the program
* output: "" * output: ""
@ -173,7 +169,7 @@ def foreground_pipe(args, cmd, working_dir=None, output_to_stdout=False,
str(args.timeout) + " seconds. Killing it.") str(args.timeout) + " seconds. Killing it.")
logging.info("NOTE: The timeout can be increased with" logging.info("NOTE: The timeout can be increased with"
" 'pmbootstrap -t'.") " 'pmbootstrap -t'.")
kill_command(args, process.pid, kill_as_root) kill_command(args, process.pid, sudo)
continue continue
# Read all currently available output # Read all currently available output
@ -222,7 +218,7 @@ def check_return_code(args, code, log_message):
def core(args, log_message, cmd, working_dir=None, output="log", def core(args, log_message, cmd, working_dir=None, output="log",
output_return=False, check=None, kill_as_root=False, disable_timeout=False): output_return=False, check=None, sudo=False, disable_timeout=False):
""" """
Run a command and create a log entry. Run a command and create a log entry.
@ -274,12 +270,12 @@ def core(args, log_message, cmd, working_dir=None, output="log",
is not 0. Set this to False to disable the check. This is not 0. Set this to False to disable the check. This
parameter can not be used when the output is "background" or parameter can not be used when the output is "background" or
"pipe". "pipe".
:param kill_as_root: use sudo to kill the process when it hits the timeout. :param sudo: use sudo to kill the process when it hits the timeout.
:returns: * program's return code (default) :returns: * program's return code (default)
* subprocess.Popen instance (output is "background" or "pipe") * subprocess.Popen instance (output is "background" or "pipe")
* the program's entire output (output_return is True) * the program's entire output (output_return is True)
""" """
sanity_checks(output, output_return, check, kill_as_root) sanity_checks(output, output_return, check)
# Log simplified and full command (pmbootstrap -v) # Log simplified and full command (pmbootstrap -v)
logging.debug(log_message) logging.debug(log_message)
@ -304,13 +300,13 @@ def core(args, log_message, cmd, working_dir=None, output="log",
if not args.details_to_stdout and output in ["stdout", "interactive"]: if not args.details_to_stdout and output in ["stdout", "interactive"]:
output_to_stdout = True output_to_stdout = True
output_timeout = output in pmb.config.run_outputs_with_timeout \ output_timeout = output in ["log", "stdout"] and not disable_timeout
and not disable_timeout
(code, output_after_run) = foreground_pipe(args, cmd, working_dir, (code, output_after_run) = foreground_pipe(args, cmd, working_dir,
output_to_stdout, output_to_stdout,
output_return, output_return,
output_timeout, output_timeout,
kill_as_root) sudo)
# Check the return code # Check the return code
if check is not False: if check is not False:

View file

@ -41,12 +41,6 @@ def test_sanity_checks():
func("tui", output_return=True) func("tui", output_return=True)
assert str(e.value).startswith("Can't use output_return with") assert str(e.value).startswith("Can't use output_return with")
# kill_as_root
func("log", kill_as_root=True)
with pytest.raises(RuntimeError) as e:
func("tui", kill_as_root=True)
assert str(e.value).startswith("Can't use kill_as_root with")
def test_background(args): def test_background(args):
# Sleep in background # Sleep in background
@ -90,7 +84,7 @@ def test_foreground_pipe(args):
cmd = ["sudo", "sh", "-c", "printf first; sleep 2; printf second"] cmd = ["sudo", "sh", "-c", "printf first; sleep 2; printf second"]
args.timeout = 0.3 args.timeout = 0.3
ret = func(args, cmd, output_return=True, output_timeout=True, ret = func(args, cmd, output_return=True, output_timeout=True,
kill_as_root=True) sudo=True)
assert ret == (-9, "first") assert ret == (-9, "first")
# Finish before timeout # Finish before timeout
@ -108,7 +102,7 @@ def test_foreground_pipe(args):
"sleep 10 | sleep 20 | sleep 30"] "sleep 10 | sleep 20 | sleep 30"]
args.timeout = 0.3 args.timeout = 0.3
ret = func(args, cmd, output_return=True, output_timeout=True, ret = func(args, cmd, output_return=True, output_timeout=True,
kill_as_root=True) sudo=True)
pgid = str(ret[1]) pgid = str(ret[1])
cmd = ["ps", "-e", "-o", "pgid=,comm=", "--noheaders"] cmd = ["ps", "-e", "-o", "pgid=,comm=", "--noheaders"]