From 32afe79aed2279a8794cdd9c99d850a5f6c28347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Po=C5=BAniak?= Date: Fri, 21 Apr 2023 10:28:58 +0200 Subject: [PATCH 1/3] Add test for killing gprofiler --- tests/test_executable.py | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/tests/test_executable.py b/tests/test_executable.py index 7fa077130..e908dd23c 100644 --- a/tests/test_executable.py +++ b/tests/test_executable.py @@ -4,8 +4,10 @@ # import os import shutil +import signal from pathlib import Path from subprocess import Popen +from threading import Event from typing import Callable, List, Mapping, Optional import pytest @@ -13,6 +15,7 @@ from docker.models.containers import Container from docker.models.images import Image +from gprofiler.utils import wait_event from gprofiler.utils.collapsed_format import parse_one_collapsed from tests.utils import RUNTIME_PROFILERS, _no_errors, run_gprofiler_in_container @@ -133,3 +136,53 @@ def test_executable_not_privileged( collapsed = parse_one_collapsed(Path(output_directory / "last_profile.col").read_text()) assert_collapsed(collapsed) + + +@pytest.mark.parametrize( + "runtime,profiler_type", + [ + ("python", "py-spy"), + ], +) +@pytest.mark.parametrize("in_container", [True]) +@pytest.mark.parametrize("application_docker_mount", [True]) +@pytest.mark.parametrize("application_docker_capabilities", ["SYS_PTRACE"]) +def test_killing_spawned_processes( + gprofiler_exe: Path, + application_docker_container: Container, + runtime_specific_args: List[str], + output_directory: Path, + profiler_flags: List[str], + application_docker_mount: bool, +) -> None: + """Tests if killing gprofiler with -9 results in killing py-spy""" + os.makedirs(str(output_directory), mode=0o755, exist_ok=True) + + mount_gprofiler_exe = str(output_directory / "gprofiler") + if not os.path.exists(mount_gprofiler_exe): + shutil.copy(str(gprofiler_exe), mount_gprofiler_exe) + + command = ( + [ + mount_gprofiler_exe, + "-v", + "--output-dir", + str(output_directory), + "--disable-pidns-check", + "--no-perf", + ] + + runtime_specific_args + + profiler_flags + ) + application_docker_container.exec_run(cmd=command, privileged=True, user="root:root", detach=True) + wait_event(30, Event(), lambda: "py-spy record" in str(application_docker_container.top().get("Processes"))) + processes_in_container = application_docker_container.top().get("Processes") + gprofiler_pids = [process[1] for process in processes_in_container if "disable-pidns-check" in process[-1]] + for pid in gprofiler_pids: + os.kill(int(pid), signal.SIGKILL) + processes_in_container = application_docker_container.top().get("Processes") + assert len(processes_in_container) == 1 + assert "py-spy record" not in str(processes_in_container) + command = ["ls", "/tmp/gprofiler_tmp"] + e, ls_output = application_docker_container.exec_run(cmd=command, privileged=True, user="root:root", detach=False) + assert "tmp" in ls_output.decode() From 0c6dbf17a709b30f16584308e9d172f395f64b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Po=C5=BAniak?= Date: Fri, 21 Apr 2023 11:45:14 +0200 Subject: [PATCH 2/3] Add debug print to test --- tests/test_executable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_executable.py b/tests/test_executable.py index 8a60528de..c73c6d300 100644 --- a/tests/test_executable.py +++ b/tests/test_executable.py @@ -185,6 +185,7 @@ def test_killing_spawned_processes( for pid in gprofiler_pids: os.kill(int(pid), signal.SIGKILL) processes_in_container = application_docker_container.top().get("Processes") + print(f"Processes left in container: {processes_in_container}") assert len(processes_in_container) == 1 assert "py-spy record" not in str(processes_in_container) command = ["ls", "/tmp/gprofiler_tmp"] From b5bd37b0b92d23ec319f173415938550f3bace7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Po=C5=BAniak?= Date: Mon, 24 Apr 2023 10:17:12 +0200 Subject: [PATCH 3/3] Ignore zombie processes left from killing gprofiler --- tests/test_executable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_executable.py b/tests/test_executable.py index c73c6d300..978e585a3 100644 --- a/tests/test_executable.py +++ b/tests/test_executable.py @@ -185,6 +185,7 @@ def test_killing_spawned_processes( for pid in gprofiler_pids: os.kill(int(pid), signal.SIGKILL) processes_in_container = application_docker_container.top().get("Processes") + processes_in_container = [process for process in processes_in_container if "" not in process[-1]] print(f"Processes left in container: {processes_in_container}") assert len(processes_in_container) == 1 assert "py-spy record" not in str(processes_in_container)