## Authors:
##   Ajrat Makhmutov <rauty@altlinux.org>
##
## Copyright (C) 2026  Basealt LLC
##
## This file is part of alterator-kopidel.
##
## alterator-kopidel is free software: you can redistribute it and/or modify it under the terms
## of the GNU General Public License as published by the Free Software Foundation,
## either version 3 of the License, or (at your option) any later version.
##
## alterator-kopidel is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
## without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
## See the GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License along with alterator-kopidel.
## If not, see <https://www.gnu.org/licenses/>.

if [ -n "${__included_kopidel_process_group-}" ]; then
	return 0
fi
readonly __included_kopidel_process_group=1

. "${KOPIDEL_LIBDIR:-/usr/lib/alterator-kopidel}/variables"

is_process_running() (
	[ -n "$1" ] && kill -0 "$1" 2>/dev/null
)

spawn_process_group() {
	if [[ $- == *m* ]]; then
		"$@" &
	else
		set -m
		"$@" &
		set +m
	fi
}

is_process_group_running() (
	[ -n "$1" ] && kill -0 -- "-$1" 2>/dev/null
)

readonly PROCESS_GROUP_TERM_TIMEOUT=10
readonly PROCESS_GROUP_KILL_TIMEOUT=5

wait_process_group_gone() (
	pid="$1"
	ticks="$(( $2 * 10 ))"
	while is_process_group_running "$pid"; do
		if [ "$ticks" -le 0 ]; then
			return 1
		fi
		(( ticks -= 1 ))
		sleep 0.1
	done
)

terminate_process_group() (
	pid="$1"
	cmd="$(ps -o cmd --no-headers fp "$pid")"
	if [[ "$cmd" != *kopidel* ]]; then
		echo "terminate_process_group: CRITICAL ERROR: TRIED TO KILL NOT KOPIDEL CMD: $cmd" >&2
		return 1
	fi

	if [ "${KOPIDEL_DEBUG-}" == 1 ]; then
		pstree "$pid" >&2
	fi

	kill -- "-$pid"
	if wait_process_group_gone "$pid" "$PROCESS_GROUP_TERM_TIMEOUT"; then
		return 0
	fi
	echo "Process group $pid ignored SIGTERM for $PROCESS_GROUP_TERM_TIMEOUT seconds, sending SIGKILL" >&2
	kill -KILL -- "-$pid" 2>/dev/null
	if ! wait_process_group_gone "$pid" "$PROCESS_GROUP_KILL_TIMEOUT"; then
		echo "Process group $pid survived SIGKILL" >&2
		return 2
	fi
)

is_build_running() (
	! flock -n "$BUILD_LOCK" true 2>/dev/null
)

running_build_workdir() (
	if is_build_running; then
		cat "$BUILD_LOCK"
	fi
)

take_build_lock() {
	exec {build_lock_fd}<>"$BUILD_LOCK" &&
		flock -n "$build_lock_fd" &&
		echo "$1" > "$BUILD_LOCK"
}
