feat: add initial procmon implementation and test

This commit is contained in:
gmega 2025-06-17 16:45:18 -03:00
commit 93187c6a91
No known key found for this signature in database
GPG Key ID: 6290D34EAD824B18
8 changed files with 163 additions and 0 deletions

9
.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[submodule "test/bats"]
path = test/bats
url = https://github.com/bats-core/bats-core.git
[submodule "test/test_helper/bats-support"]
path = test/test_helper/bats-support
url = https://github.com/bats-core/bats-support.git
[submodule "test/test_helper/bats-assert"]
path = test/test_helper/bats-assert
url = https://github.com/bats-core/bats-assert.git

2
src/config.bash Normal file
View File

@ -0,0 +1,2 @@
LIB_SRC=${LIB_SRC:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}
OUTPUTS=${OUTPUTS:-${LIB_SRC}/../outputs}

89
src/process_monitor.bash Normal file
View File

@ -0,0 +1,89 @@
#!/usr/bin/env bash
LIB_SRC=${LIB_SRC:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}
# shellcheck source=./config.bash
source "${LIB_SRC}/config.bash"
# shellcheck source=./utils.bash
source "${LIB_SRC}/utils.bash"
_procmon_output=$(clh_output_folder "procmon")
_procmon_pid=""
_procmon_init_output() {
rm -rf "${_procmon_output}" || true
mkdir -p "${_procmon_output}"
}
clh_start_process_monitor() {
_procmon_init_output
if [ -n "$_procmon_pid" ]; then
echoerr "[procmon] process monitor already started"
return 1
fi
local pid=$$
_pgid=$(ps -o pgid= -p ${pid} | sed 's/ //g')
export _pgid
export _procmon_output
echoerr "[procmon] start"
(
shutdown=false
while ! $shutdown; do
for pid_file in "${_procmon_output}"/*.pid; do
[[ -f "${pid_file}" ]] || continue # null glob
base_name=$(basename "${pid_file}")
pid=${base_name%.pid}
if ! kill -0 "${pid}"; then
echoerr "[procmon] ${pid} is dead"
rm "${pid_file}"
fi
sleep 1
done
done
) &
_procmon_pid=$!
echoerr "[procmon] started with PID $_procmon_pid"
return 0
}
clh_track_last_background_job() {
local pid=$!
if [ ! -f "${_procmon_output}/${pid}.pid" ]; then
touch "${_procmon_output}/${pid}.pid"
fi
}
clh_get_tracked_pids() {
result=()
for pid_file in "${_procmon_output}"/*.pid; do
base_name=$(basename "${pid_file}")
pid=${base_name%.pid}
result+=("${pid}")
done
}
clh_stop_process_monitor() {
if [ -z "$_procmon_pid" ]; then
echoerr "[procmon] process monitor not started"
return 1
fi
if ! kill -0 "$_procmon_pid"; then
echoerr "[procmon] process monitor not running"
return 1
fi
if [ "$1" = "monitor_only" ]; then
echoerr "[procmon] stop monitor only. Children will be left behind."
kill -s TERM "$_procmon_pid"
wait "$_procmon_pid"
return 0
else
echoerr "[procmon] stop process group. This will halt the script."
kill -s TERM "-$_pgid"
fi
}

14
src/utils.bash Normal file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
LIB_SRC=${LIB_SRC:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}
# shellcheck source=./config.bash
source "${LIB_SRC}/config.bash"
clh_output_folder() {
echo "${OUTPUTS}/$1"
}
echoerr() {
echo "$@" >&2
}

1
test/bats Submodule

@ -0,0 +1 @@
Subproject commit 941bf35348987999cb510b17f4c59b67486aa818

@ -0,0 +1 @@
Subproject commit 035e99c84759427bf160a6613904e9d57f838ea9

@ -0,0 +1 @@
Subproject commit d007fc1f451abbad55204fa9c9eb3e6ed5dc5f61

View File

@ -0,0 +1,46 @@
setup() {
bats_require_minimum_version 1.12.0
export LIB_SRC="${BATS_TEST_DIRNAME}/../src"
load "${BATS_TEST_DIRNAME}/test_helper/bats-support/load.bash"
load "${BATS_TEST_DIRNAME}/test_helper/bats-assert/load.bash"
source "${LIB_SRC}/process_monitor.bash"
}
@test "should not start process monitor twice" {
assert clh_start_process_monitor
refute clh_start_process_monitor
assert clh_stop_process_monitor "monitor_only"
}
@test "should not stop the process monitor if it wasn't started" {
refute clh_stop_process_monitor
}
# @test "should keep track of process PIDs" {
# clh_get_tracked_pids
# assert [ ${#result[@]} -eq 0 ]
# (
# while [ ! -f "${OUTPUT_FOLDER}/stop" ]; do
# sleep 0.1
# done
# ) &
# clh_track_last_background_job
# (
# while [ ! -f "${OUTPUT_FOLDER}/stop" ]; do
# sleep 0.1
# done
# ) &
# clh_track_last_background_job
# clh_get_tracked_pids
# assert [ ${#result[@]} -eq 2 ]
# touch "${OUTPUT_FOLDER}/stop"
# clh_get_tracked_pids
# assert [ ${#result[@]} -eq 0 ]
# }