Skip to content
Merged
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
32 changes: 31 additions & 1 deletion granulate_utils/linux/elf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,42 @@
#

import hashlib
from typing import Optional, cast
from functools import wraps
from typing import Callable, Optional, TypeVar, cast

import psutil
from elftools.elf.elffile import ELFError, ELFFile # type: ignore
from elftools.elf.sections import NoteSection # type: ignore
from typing_extensions import ParamSpec

__all__ = ["ELFError"]

P = ParamSpec("P")
R = TypeVar("R")


def raise_nosuchprocess(func: Callable[P, R]) -> Callable[P, R]:
@wraps(func)
def inner(*args: P.args, **kwargs: P.kwargs):
try:
return func(*args, **kwargs)
except FileNotFoundError as e:
# Check if filename is /proc/{pid}/*
if e.filename.startswith("/proc/"):
if e.filename.split("/")[2].isalnum():
# Take pid from /proc/{pid}/*
pid = int(e.filename.split("/")[2])
# Check if number from /proc/{pid} is actually a pid number
with open("/proc/sys/kernel/pid_max") as pid_max_file:
pid_max = int(pid_max_file.read())
if pid <= pid_max:
# Check if pid is running
if not psutil.pid_exists(pid):
Copy link
Contributor

Choose a reason for hiding this comment

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

It is true though, that pid_exists is a better check than what we have in read_proc_file - we use os.path.exists("/proc/pid"), but this will return True also if pid is a tid of another process (e.g due to reuse). pid_exists uses different means to check, to avoid this confusion. Note @d3dave .

Copy link
Contributor

@d3dave d3dave Oct 10, 2022

Choose a reason for hiding this comment

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

I assume that in read_proc_file we do not want to support PIDs only. I can see value in reading a specific thread's mountinfo, ns/*, stat, etc.

Copy link
Contributor

@d3dave d3dave Oct 10, 2022

Choose a reason for hiding this comment

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

Also, instead of exists(/proc/pid) should have just kill(pid, 0). (Hmmm, pretty sure I copied that from psutil...)

Copy link
Contributor

Choose a reason for hiding this comment

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

pid_exists does extra checks because they claim os.kill is bad as well :dumb:

raise psutil.NoSuchProcess(pid)
raise e

return inner


def get_elf_arch(path: str) -> str:
"""
Expand Down Expand Up @@ -39,6 +68,7 @@ def get_elf_buildid(path: str) -> Optional[str]:
return None


@raise_nosuchprocess
def get_elf_id(path: str) -> str:
"""
Gets an identifier for this ELF.
Expand Down