From 6bb2f1dd1b7e494a4975248a3f6449ccb87a0fef Mon Sep 17 00:00:00 2001 From: Ariel Moshe Date: Wed, 14 Sep 2022 15:50:25 +0300 Subject: [PATCH 1/7] Added golang and node process utils --- granulate_utils/golang.py | 41 +++++++++++++++++++++++++++++++++++++++ granulate_utils/node.py | 6 ++++++ 2 files changed, 47 insertions(+) create mode 100644 granulate_utils/golang.py create mode 100644 granulate_utils/node.py diff --git a/granulate_utils/golang.py b/granulate_utils/golang.py new file mode 100644 index 00000000..b6a70e49 --- /dev/null +++ b/granulate_utils/golang.py @@ -0,0 +1,41 @@ +# +# Copyright (c) Granulate. All rights reserved. +# Licensed under the AGPL3 License. See LICENSE.md in the project root for license information. +# +import functools +import struct +from typing import Optional + +from psutil import NoSuchProcess, Process + +from granulate_utils.linux.elf import read_elf_symbol, read_elf_va + + +def is_golang_process(process: Process) -> bool: + return get_process_golang_version(process) is not None + + +@functools.lru_cache(maxsize=4096) +def get_process_golang_version(process: Process) -> Optional[str]: + elf_path = f"/proc/{process.pid}/exe" + try: + symbol_data = read_elf_symbol(elf_path, "runtime.buildVersion", 16) + except FileNotFoundError: + raise NoSuchProcess(process.pid) + if symbol_data is None: + return None + + # Declaration of go string type: + # type stringStruct struct { + # str unsafe.Pointer + # len int + # } + addr, length = struct.unpack("QQ", symbol_data) + try: + golang_version_bytes = read_elf_va(elf_path, addr, length) + except FileNotFoundError: + raise NoSuchProcess(process.pid) + if golang_version_bytes is None: + return None + + return golang_version_bytes.decode() diff --git a/granulate_utils/node.py b/granulate_utils/node.py new file mode 100644 index 00000000..095c2071 --- /dev/null +++ b/granulate_utils/node.py @@ -0,0 +1,6 @@ +# +# Copyright (c) Granulate. All rights reserved. +# Licensed under the AGPL3 License. See LICENSE.md in the project root for license information. +# + +DETECTED_PYTHON_PROCESSES_REGEX = r"^.+/libnode\.so" From 381958acea3b0681ae513f2e2ee2244bd53d70a7 Mon Sep 17 00:00:00 2001 From: Ariel Moshe Date: Wed, 14 Sep 2022 15:56:37 +0300 Subject: [PATCH 2/7] Fixed wrong variable name --- granulate_utils/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/granulate_utils/node.py b/granulate_utils/node.py index 095c2071..508aa3ae 100644 --- a/granulate_utils/node.py +++ b/granulate_utils/node.py @@ -3,4 +3,4 @@ # Licensed under the AGPL3 License. See LICENSE.md in the project root for license information. # -DETECTED_PYTHON_PROCESSES_REGEX = r"^.+/libnode\.so" +DETECTED_NODE_PROCESSES_REGEX = r"^.+/libnode\.so" From 8f319f2c63e2b31aea0d7a3136d01b56de7ca5f6 Mon Sep 17 00:00:00 2001 From: Ariel Moshe Date: Wed, 14 Sep 2022 15:58:10 +0300 Subject: [PATCH 3/7] Added blank line --- granulate_utils/golang.py | 1 + 1 file changed, 1 insertion(+) diff --git a/granulate_utils/golang.py b/granulate_utils/golang.py index b6a70e49..db080d57 100644 --- a/granulate_utils/golang.py +++ b/granulate_utils/golang.py @@ -2,6 +2,7 @@ # Copyright (c) Granulate. All rights reserved. # Licensed under the AGPL3 License. See LICENSE.md in the project root for license information. # + import functools import struct from typing import Optional From a3fde1be2fda90b24f6dfdbda49c483cdc8257e3 Mon Sep 17 00:00:00 2001 From: Ariel Moshe Date: Thu, 15 Sep 2022 15:08:16 +0300 Subject: [PATCH 4/7] Changed node process detection --- granulate_utils/node.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/granulate_utils/node.py b/granulate_utils/node.py index 508aa3ae..3ee028e2 100644 --- a/granulate_utils/node.py +++ b/granulate_utils/node.py @@ -3,4 +3,12 @@ # Licensed under the AGPL3 License. See LICENSE.md in the project root for license information. # -DETECTED_NODE_PROCESSES_REGEX = r"^.+/libnode\.so" +import os + +from psutil import Process + +from granulate_utils.linux.process import process_exe + + +def is_node_process(process: Process) -> bool: + return os.path.basename(process_exe(process)) == "node" From d26bd195f8ab49affb268ba2a5e601f188909ae6 Mon Sep 17 00:00:00 2001 From: Ariel Moshe Date: Thu, 15 Sep 2022 15:21:57 +0300 Subject: [PATCH 5/7] Updated process detection based on new gProfiler commit --- granulate_utils/linux/process.py | 17 ++++++++++++++++- granulate_utils/node.py | 4 ++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/granulate_utils/linux/process.py b/granulate_utils/linux/process.py index 7e800681..931c3888 100644 --- a/granulate_utils/linux/process.py +++ b/granulate_utils/linux/process.py @@ -2,8 +2,10 @@ # Copyright (c) Granulate. All rights reserved. # Licensed under the AGPL3 License. See LICENSE.md in the project root for license information. # - +import os +import re import struct +from functools import lru_cache from typing import Optional import psutil @@ -95,3 +97,16 @@ def read_process_execfn(process: psutil.Process) -> str: addr = _read_process_auxv(process, AT_EXECFN) fn = _read_process_memory(process, addr, PATH_MAX) return fn[: fn.index(b"\0")].decode() + + +@lru_cache(maxsize=512) +def is_process_basename_matching(process: psutil.Process, basename_pattern: str) -> bool: + if re.match(basename_pattern, os.path.basename(process_exe(process))): + return True + + # process was executed AS basename (but has different exe name) + cmd = process.cmdline() + if len(cmd) > 0 and re.match(basename_pattern, cmd[0]): + return True + + return False diff --git a/granulate_utils/node.py b/granulate_utils/node.py index 3ee028e2..e0a55ac3 100644 --- a/granulate_utils/node.py +++ b/granulate_utils/node.py @@ -7,8 +7,8 @@ from psutil import Process -from granulate_utils.linux.process import process_exe +from granulate_utils.linux.process import is_process_basename_matching def is_node_process(process: Process) -> bool: - return os.path.basename(process_exe(process)) == "node" + return is_process_basename_matching(process, r"^node$") From 7f2ba981a6358822e345382ba85a0b1b70b98e8e Mon Sep 17 00:00:00 2001 From: Ariel Moshe Date: Thu, 15 Sep 2022 15:24:02 +0300 Subject: [PATCH 6/7] Removed unused import --- granulate_utils/node.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/granulate_utils/node.py b/granulate_utils/node.py index e0a55ac3..45344820 100644 --- a/granulate_utils/node.py +++ b/granulate_utils/node.py @@ -3,8 +3,6 @@ # Licensed under the AGPL3 License. See LICENSE.md in the project root for license information. # -import os - from psutil import Process from granulate_utils.linux.process import is_process_basename_matching From 0e3491476a3db3542e44b212589ac8fa20201228 Mon Sep 17 00:00:00 2001 From: Ariel Moshe Date: Mon, 19 Sep 2022 18:19:14 +0300 Subject: [PATCH 7/7] CR fixes --- granulate_utils/golang.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/granulate_utils/golang.py b/granulate_utils/golang.py index db080d57..719633cd 100644 --- a/granulate_utils/golang.py +++ b/granulate_utils/golang.py @@ -10,6 +10,7 @@ from psutil import NoSuchProcess, Process from granulate_utils.linux.elf import read_elf_symbol, read_elf_va +from granulate_utils.linux.process import process_exe def is_golang_process(process: Process) -> bool: @@ -18,7 +19,7 @@ def is_golang_process(process: Process) -> bool: @functools.lru_cache(maxsize=4096) def get_process_golang_version(process: Process) -> Optional[str]: - elf_path = f"/proc/{process.pid}/exe" + elf_path = process_exe(process) try: symbol_data = read_elf_symbol(elf_path, "runtime.buildVersion", 16) except FileNotFoundError: