some fixes
This commit is contained in:
@@ -10,6 +10,11 @@ REQUIREMENTS_FILE="${PROJECT_ROOT}/requirements.txt"
|
||||
PYTHON_CMD=""
|
||||
PROFILE_PATH=""
|
||||
|
||||
# Single-instance coordination: the headless daemon and the interactive GUI
|
||||
# must never run at once (they share the radar, SHM rings and locator port).
|
||||
SERVICE_NAME="radar.service"
|
||||
LOCK_FILE="/tmp/radar_system.lock"
|
||||
|
||||
SKIP_BUILD=0
|
||||
BUILD_ONLY=0
|
||||
CLEAN_SHM=0
|
||||
@@ -154,6 +159,15 @@ ensure_python_dependencies() {
|
||||
return
|
||||
fi
|
||||
|
||||
if ((HEADLESS == 1)); then
|
||||
# Headless = unattended (often offline) appliance: never attempt a network
|
||||
# pip install that could hang or crash-loop the service. Provisioning is a
|
||||
# one-time interactive step. Fail fast with a clear, actionable message.
|
||||
echo "Python dependencies are missing and headless mode does not provision them." >&2
|
||||
echo "Run an interactive './start.sh' once (online) to create the venv, then retry." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[start.sh] Installing Python dependencies into virtual environment..."
|
||||
"${VENV_PIP}" install --upgrade pip
|
||||
"${VENV_PIP}" install -r "${REQUIREMENTS_FILE}"
|
||||
@@ -311,11 +325,58 @@ run_producer_only() {
|
||||
exec "${PYTHON_CMD}" -m python_app.scripts.kamil_adc_raw_producer --config "${PROFILE_PATH}"
|
||||
}
|
||||
|
||||
stop_headless_service() {
|
||||
# Stop the headless daemon (if running) so it releases the radar, SHM rings
|
||||
# and locator port before the interactive GUI/producer takes over. Relies on
|
||||
# the passwordless sudoers rule installed by deploy/install-daemon.sh. Safe
|
||||
# no-op when systemd or the unit is absent (is-active is false -> skip).
|
||||
command -v systemctl >/dev/null 2>&1 || return 0
|
||||
if systemctl is-active --quiet "${SERVICE_NAME}"; then
|
||||
echo "[start.sh] Stopping ${SERVICE_NAME} so the GUI can take over the hardware..."
|
||||
# Non-fatal: a sudo/systemctl failure must not abort the GUI launch under
|
||||
# `set -e`. The single-instance lock below still prevents a real conflict.
|
||||
if ! sudo systemctl stop "${SERVICE_NAME}"; then
|
||||
echo "[start.sh] WARNING: failed to stop ${SERVICE_NAME}; relying on the instance lock." >&2
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
verify_cpp_binaries() {
|
||||
# Guard the daemon's --skip-build path: refuse to run against a tree whose C++
|
||||
# binaries were never built, instead of failing obscurely at spawn time.
|
||||
local missing=0 bin
|
||||
for bin in data_processor data_preprocessor; do
|
||||
if [[ ! -x "${PROJECT_ROOT}/build/bin/${bin}" ]]; then
|
||||
echo "Required binary missing or not executable: build/bin/${bin}" >&2
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
if ((missing == 1)); then
|
||||
echo "Build the C++ binaries first: run ./start.sh without --skip-build, or 'make all'." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
acquire_single_instance_lock() {
|
||||
# Fail fast if another instance already owns the hardware, instead of
|
||||
# surfacing a cryptic 'shm ring busy' / 'port in use' later. fd 9 survives
|
||||
# the exec into Python, so the lock is held for the whole app lifetime.
|
||||
exec 9>"${LOCK_FILE}"
|
||||
if ! flock -n 9; then
|
||||
echo "[start.sh] Another radar instance already holds ${LOCK_FILE}; aborting." >&2
|
||||
echo "[start.sh] Stop it first: sudo systemctl stop ${SERVICE_NAME} (or close the other run)." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
parse_args "$@"
|
||||
resolve_profile_path
|
||||
check_environment
|
||||
if ((KAMIL_ADC_MODE == 0)); then
|
||||
# Skip first-time provisioning (build headers, USB udev rule) in headless
|
||||
# mode: the daemon runs unattended at boot as a non-root user and must not
|
||||
# block on sudo. A fresh machine is provisioned by one interactive launch.
|
||||
if ((KAMIL_ADC_MODE == 0 && HEADLESS == 0)); then
|
||||
ensure_system_dependencies
|
||||
ensure_usb_access_rules
|
||||
fi
|
||||
@@ -329,11 +390,21 @@ main() {
|
||||
build_cpp_binaries
|
||||
fi
|
||||
|
||||
verify_cpp_binaries
|
||||
|
||||
if ((BUILD_ONLY == 1)); then
|
||||
echo "[start.sh] Build completed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Interactive GUI/producer launch: stop the headless daemon first so it
|
||||
# frees the radar, SHM and locator port. The daemon itself runs --headless
|
||||
# and skips this, so it never stops itself.
|
||||
if ((HEADLESS == 0)); then
|
||||
stop_headless_service
|
||||
fi
|
||||
acquire_single_instance_lock
|
||||
|
||||
if ((PRODUCER_ONLY == 1)); then
|
||||
run_producer_only
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user