1# Copyright (c) 2023 Nordic Semiconductor ASA 2# 3# SPDX-License-Identifier: Apache-2.0 4 5from __future__ import annotations 6 7import logging 8import os 9import platform 10import shlex 11import signal 12import subprocess 13import time 14 15import psutil 16 17_WINDOWS = platform.system() == 'Windows' 18 19 20def log_command(logger: logging.Logger, msg: str, args: list, level: int = logging.DEBUG) -> None: 21 """ 22 Platform-independent helper for logging subprocess invocations. 23 24 Will log a command string that can be copy/pasted into a POSIX 25 shell on POSIX platforms. This is not available on Windows, so 26 the entire args array is logged instead. 27 28 :param logger: logging.Logger to use 29 :param msg: message to associate with the command 30 :param args: argument list as passed to subprocess module 31 :param level: log level 32 """ 33 msg = f'{msg}: %s' 34 if _WINDOWS: 35 logger.log(level, msg, str(args)) 36 else: 37 logger.log(level, msg, shlex.join(args)) 38 39 40def terminate_process(proc: subprocess.Popen) -> None: 41 """ 42 Try to terminate provided process and all its subprocesses recursively. 43 """ 44 for child in psutil.Process(proc.pid).children(recursive=True): 45 try: 46 os.kill(child.pid, signal.SIGTERM) 47 except ProcessLookupError: 48 pass 49 proc.terminate() 50 # sleep for a while before attempting to kill 51 time.sleep(0.5) 52 proc.kill() 53