Skip to content

Attach manual processes to executor and executor processes to resource monitoring #416

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

Merged
merged 27 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e549458
Merge branch 'hotfix/add-multi-process-test' into v1.0-rc
kzscisoft Jun 4, 2024
e0ef077
Merge branch 'hotfix/fix-offline-no-init-no-name' into v1.0-rc
kzscisoft Jun 5, 2024
912b57b
Merge branch 'hotfix/handle-numpy-object-response' into v1.0-rc
kzscisoft Jun 5, 2024
aa2c5ad
Merge branch 'hotfix/check-for-none-not-unempty' into v1.0-rc
kzscisoft Jun 7, 2024
2da82bc
Merge branch 'hotfix/388-git-repo-metadata-crash' into v1.0-rc
kzscisoft Jun 7, 2024
fc5b619
Merge branch 'hotfix/return-self-runs-by-default' into v1.0-rc
kzscisoft Jun 7, 2024
b173fed
Merge branch 'hotfix/share-ci-not-local-test-runs' into v1.0-rc
kzscisoft Jun 7, 2024
5f110f3
Merge branch 'hotfix/add-no-print-to-hooks' into v1.0-rc
kzscisoft Jun 7, 2024
53929b1
[skip ci]Merge branch 'hotfix/update-lock' into v1.0-rc
kzscisoft Jun 7, 2024
43dcb4c
[no ci] Merge branch 'hotfix/non-color-mode' into v1.0-rc
kzscisoft Jun 7, 2024
b9d822b
[skip ci]Merge branch 'hotfix/test-other-python-on-rc' into v1.0-rc
kzscisoft Jun 7, 2024
7ee20ff
Merge branch 'hotfix/add-abort-alert-option' into v1.0-rc
kzscisoft Jun 7, 2024
c83cb82
Merge branch 'hotfix/fix-git-metadata' into v1.0-rc
kzscisoft Jun 7, 2024
9af590c
Merge branch 'hotfix/fix-posix-in-str' into v1.0-rc
kzscisoft Jun 7, 2024
81dfa19
Merge branch 'hotfix/fix-posix-in-str' into v1.0-rc
kzscisoft Jun 7, 2024
736a3b1
[skip ci]Merge branch 'hotfix/change-log' into v1.0-rc
kzscisoft Jun 10, 2024
49b00a3
[skip ci]Merge branch 'hotfix/fix-warning-check-test' into v1.0-rc
kzscisoft Jun 10, 2024
f3ebc2e
Merge branch 'hotfix/handle-no-git' into v1.0-rc
kzscisoft Jun 10, 2024
3a7b423
Merge branch 'feature/auto-abort' into v1.0-rc
kzscisoft Jun 10, 2024
bd0c093
Merge branch 'hotfix/handle-no-results-metrics' into v1.0-rc
kzscisoft Jun 10, 2024
fcafcb1
Merge branch 'hotfix/ci-manual' into v1.0-rc
kzscisoft Jun 12, 2024
ac60490
Merge branch 'hotfix/kill-all-on-exception' into v1.0-rc
kzscisoft Jun 12, 2024
7af8059
Merge branch 'hotfix/wrong-error-types' into v1.0-rc
kzscisoft Jun 12, 2024
032f76e
Remove dev from version
kzscisoft Jun 12, 2024
ed6250f
Attach processes run by executor to process list
kzscisoft Jun 12, 2024
a787a74
Fixed log message position
kzscisoft Jun 12, 2024
f973470
Fix wrong comparison in process PID check
kzscisoft Jun 12, 2024
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "simvue"
version = "1.0.0.dev2"
version = "1.0.0"
description = "Simulation tracking and monitoring"
authors = ["Simvue Development Team <[email protected]>"]
license = "Apache v2"
Expand Down
61 changes: 49 additions & 12 deletions simvue/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
__date__ = "2023-11-15"

import logging
import contextlib
import multiprocessing.synchronize
import sys
import multiprocessing
Expand Down Expand Up @@ -205,6 +206,24 @@ def callback_function(status_code: int, std_out: str, std_err: str) -> None:
name=f"{identifier}_exit_status", source="user"
)

@property
def processes(self) -> list[psutil.Process]:
"""Create an array containing a list of processes"""
if not self._processes:
return []

_all_processes: list[psutil.Process] = [
psutil.Process(process.pid) for process in self._processes.values()
]

with contextlib.suppress(psutil.NoSuchProcess, psutil.ZombieProcess):
for process in _all_processes:
for child in process.children(recursive=True):
if child not in _all_processes:
_all_processes.append(child)

return list(set(_all_processes))

@property
def success(self) -> int:
"""Return whether all attached processes completed successfully"""
Expand Down Expand Up @@ -294,15 +313,31 @@ def _save_output(self) -> None:
f"{self._runner.name}_{proc_id}.out", category="output"
)

def kill_process(self, process_id: str) -> None:
"""Kill a running process by ID"""
if not (process := self._processes.get(process_id)):
logger.error(
f"Failed to terminate process '{process_id}', no such identifier."
)
return
def kill_process(
self, process_id: typing.Union[int, str], kill_children_only: bool = False
) -> None:
"""Kill a running process by ID

parent = psutil.Process(process.pid)
If argument is a string this is a process handled by the client,
else it is a PID of a external monitored process

Parameters
----------
process_id : typing.Union[int, str]
either the identifier for a client created process or the PID
of an external process
kill_children_only : bool, optional
if process_id is an integer, whether to kill only its children
"""
if isinstance(process_id, str):
if not (process := self._processes.get(process_id)):
logger.error(
f"Failed to terminate process '{process_id}', no such identifier."
)
return
parent = psutil.Process(process.pid)
elif isinstance(process_id, int):
parent = psutil.Process(process_id)

for child in parent.children(recursive=True):
logger.debug(f"Terminating child process {child.pid}: {child.name()}")
Expand All @@ -311,11 +346,13 @@ def kill_process(self, process_id: str) -> None:
for child in parent.children(recursive=True):
child.wait()

logger.debug(f"Terminating child process {process.pid}: {process.args}")
process.kill()
process.wait()
if not kill_children_only:
logger.debug(f"Terminating process {process.pid}: {process.args}")
process.kill()
process.wait()

self._execute_callback(process_id)
if isinstance(process_id, str):
self._execute_callback(process_id)

def kill_all(self) -> None:
"""Kill all running processes"""
Expand Down
22 changes: 17 additions & 5 deletions simvue/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,17 +216,21 @@ def time_stamp(self) -> str:
@property
def processes(self) -> list[psutil.Process]:
"""Create an array containing a list of processes"""

process_list = self._executor.processes

if not self._parent_process:
return []
return process_list

_all_processes: list[psutil.Process] = [self._parent_process]
process_list += [self._parent_process]

# Attach child processes relating to the process set by set_pid
with contextlib.suppress(psutil.NoSuchProcess, psutil.ZombieProcess):
for child in self._parent_process.children(recursive=True):
if child not in _all_processes:
_all_processes.append(child)
if child not in process_list:
process_list.append(child)

return list(set(_all_processes))
return list(set(process_list))

def _get_sysinfo(self) -> dict[str, typing.Any]:
"""Retrieve system administration
Expand Down Expand Up @@ -779,6 +783,14 @@ def kill_process(self, process_id: str) -> None:

def kill_all_processes(self) -> None:
"""Kill all currently running processes."""
# Dont kill the manually attached process if it is the current script
# but do kill its children. The kill process method of executor by
# default refers to its own processes but can also be used on a PID
if self._parent_process:
self._executor.kill_process(
process_id=self._parent_process.pid,
kill_children_only=self._parent_process.pid == os.getpid(),
)
self._executor.kill_all()

@property
Expand Down
Loading