Skip to content

Commit fef1e28

Browse files
committed
wait before profiling newly created containers
1 parent 86995b1 commit fef1e28

File tree

10 files changed

+68
-93
lines changed

10 files changed

+68
-93
lines changed

gprofiler/containers_client.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
#
16+
import time
1617
from typing import Dict, List, Optional, Set
1718

1819
from granulate_utils.containers.client import ContainersClient
@@ -25,6 +26,8 @@
2526

2627
logger = get_logger_adapter(__name__)
2728

29+
NEWLY_CREATED_CONTAINER_AGE_IN_SECONDS = 3
30+
2831

2932
class ContainerNamesClient:
3033
def __init__(self) -> None:
@@ -73,9 +76,13 @@ def get_container_name(self, pid: int) -> str:
7376
def _safely_get_process_container_name(self, pid: int) -> Optional[str]:
7477
try:
7578
try:
76-
container_id = get_process_container_id(Process(pid))
79+
process = Process(pid)
80+
container_id = get_process_container_id(process)
7781
if container_id is None:
7882
return None
83+
# If the container is newly created, we wait a bit to make sure the container is available
84+
if time.time() - process.create_time() <= NEWLY_CREATED_CONTAINER_AGE_IN_SECONDS:
85+
time.sleep(2)
7986
except NoSuchProcess:
8087
return None
8188
return self._get_container_name(container_id)

gprofiler/profilers/java.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,7 @@ def _check_async_profiler_loaded(self, process: Process) -> bool:
12291229
def _profile_process(self, process: Process, duration: int, spawned: bool) -> ProfileData:
12301230
comm = process_comm(process)
12311231
exe = process_exe(process)
1232+
container_name = self._profiler_state.get_container_name(process.pid)
12321233
java_version_output: Optional[str] = get_java_version_logged(process, self._profiler_state.stop_event)
12331234

12341235
if self._enabled_proc_events_java:
@@ -1258,7 +1259,6 @@ def _profile_process(self, process: Process, duration: int, spawned: bool) -> Pr
12581259
self._profiled_pids.add(process.pid)
12591260

12601261
logger.info(f"Profiling{' spawned' if spawned else ''} process {process.pid} with async-profiler")
1261-
container_name = self._profiler_state.get_container_name(process.pid)
12621262
app_metadata = self._metadata.get_metadata(process)
12631263
appid = application_identifiers.get_java_app_id(process, self._collect_spark_app_name)
12641264

gprofiler/profilers/php.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,11 @@ def extract_metadata_section(re_expr: Pattern, metadata_line: str) -> str:
210210
if profiler_state.processes_to_profile is not None:
211211
if pid not in [process.pid for process in profiler_state.processes_to_profile]:
212212
continue
213+
container_name = profiler_state.get_container_name(pid)
213214
# TODO: appid & app metadata for php!
214215
appid = None
215216
app_metadata = None
216-
profiles[pid] = ProfileData(results[pid], appid, app_metadata, profiler_state.get_container_name(pid))
217+
profiles[pid] = ProfileData(results[pid], appid, app_metadata, container_name)
217218

218219
return profiles
219220

gprofiler/profilers/python_ebpf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,9 @@ def snapshot(self) -> ProcessToProfileData:
262262
if self._profiler_state.processes_to_profile is not None:
263263
if process not in self._profiler_state.processes_to_profile:
264264
continue
265+
container_name = self._profiler_state.get_container_name(pid)
265266
appid = application_identifiers.get_python_app_id(process)
266267
app_metadata = self._metadata.get_metadata(process)
267-
container_name = self._profiler_state.get_container_name(pid)
268268
except NoSuchProcess:
269269
appid = None
270270
app_metadata = None

gprofiler/utils/__init__.py

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -90,45 +90,7 @@ def is_root() -> bool:
9090
return os.geteuid() == 0
9191

9292

93-
libc: Optional[ctypes.CDLL] = None
94-
95-
96-
def prctl(*argv: Any) -> int:
97-
global libc
98-
if libc is None:
99-
libc = ctypes.CDLL("libc.so.6", use_errno=True)
100-
return cast(int, libc.prctl(*argv))
101-
102-
103-
PR_SET_PDEATHSIG = 1
104-
105-
106-
def set_child_termination_on_parent_death() -> int:
107-
ret = prctl(PR_SET_PDEATHSIG, signal.SIGTERM)
108-
if ret != 0:
109-
errno = ctypes.get_errno()
110-
logger.warning(
111-
f"Failed to set parent-death signal on child process. errno: {errno}, strerror: {os.strerror(errno)}"
112-
)
113-
return ret
114-
115-
116-
def wrap_callbacks(callbacks: List[Callable]) -> Callable:
117-
# Expects array of callback.
118-
# Returns one callback that call each one of them, and returns the retval of last callback
119-
def wrapper() -> Any:
120-
ret = None
121-
for cb in callbacks:
122-
ret = cb()
123-
124-
return ret
125-
126-
return wrapper
127-
128-
129-
def start_process(
130-
cmd: Union[str, List[str]], via_staticx: bool = False, term_on_parent_death: bool = True, **kwargs: Any
131-
) -> Popen:
93+
def start_process(cmd: Union[str, List[str]], via_staticx: bool = False, **kwargs: Any) -> Popen:
13294
if isinstance(cmd, str):
13395
cmd = [cmd]
13496

@@ -150,19 +112,12 @@ def start_process(
150112
env = env if env is not None else os.environ.copy()
151113
env.update({"LD_LIBRARY_PATH": ""})
152114

153-
if is_windows():
154-
cur_preexec_fn = None # preexec_fn is not supported on Windows platforms. subprocess.py reports this.
155-
else:
156-
cur_preexec_fn = kwargs.pop("preexec_fn", os.setpgrp)
157-
if term_on_parent_death:
158-
cur_preexec_fn = wrap_callbacks([set_child_termination_on_parent_death, cur_preexec_fn])
159-
160115
popen = Popen(
161116
cmd,
162117
stdout=kwargs.pop("stdout", subprocess.PIPE),
163118
stderr=kwargs.pop("stderr", subprocess.PIPE),
164119
stdin=subprocess.PIPE,
165-
preexec_fn=cur_preexec_fn,
120+
start_new_session=is_linux(), # TODO: change to "process_group" after upgrade to Python 3.11+
166121
env=env,
167122
**kwargs,
168123
)

0 commit comments

Comments
 (0)