Skip to content

wittier caching and exe getting for golang #150

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions granulate_utils/golang.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
import struct
from typing import Optional

from psutil import NoSuchProcess, Process
from psutil import NoSuchProcess, Process, pids

from granulate_utils.linux.elf import read_elf_symbol, read_elf_va
from granulate_utils.linux.process import is_kernel_thread
from granulate_utils.linux.ns import get_mnt_ns_ancestor
from granulate_utils.linux.process import is_kernel_thread, process_exe


def is_golang_process(process: Process) -> bool:
Expand All @@ -19,14 +20,29 @@ 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"
try:
exe = process_exe(process)
except:
return None
elf_path = f"/proc/{get_mnt_ns_ancestor(process).pid}/root{exe}"
return get_version_hidden_in_exe(elf_path, process.create_time())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version should be cached for a path and its modification time. Depending on process' create_time will reduce the effect of caching - every new process has new create time.
It won't be possible for a new process to reuse version info cached earlier.




@functools.lru_cache(maxsize=4096)
def get_version_hidden_in_exe(elf_path: str, process_start_time: float) -> Optional[str]:
process = None
for pid in pids():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using psutil.process_iter(), as it's caching created Process instances, and yields only live processes.
Note that this method reads additional process attributes - might limit them to create_time and exe.

if Process(pid).create_time() == process_start_time:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this condition enough? create_time has one second granularity, I'm concerned about raising NoSuchProcess few lines later.

process = Process(pid)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to break the iteration early at this point.

if process is None:
raise NoSuchProcess(process)
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
Expand Down