#!/bin/sh # Keep daed as a child so signals can be forwarded and stale netns/veth # state can be cleaned before start and after exit. daed owns TC detach; # /sys/fs/bpf/daed is normal persistent state and is never removed here. . /usr/share/daed/cleanup.sh # Pre-start cleanup refuses to remove runtime state while another # daed instance is active, and fails closed if that probe is broken. DAED_GUARD_CLEANUP=start if ! daed_cleanup_runtime; then echo "daed: stale /usr/bin/daed or netns state could not be verified or removed; refusing to start. Check process and netns state." >&2 logger -t daed-init "pre-start cleanup failed: refusing to start daed" exit 1 fi # Keep daed as a child so post-exit cleanup runs before procd can # respawn it. child_pid= pending_signal= shutdown_signal= shutdown_elapsed=0 forced_kill=0 child_term_timeout=20 forward_signal() { local sig="$1" if [ -z "$child_pid" ]; then pending_signal="$sig" logger -t daed-init "signal $sig received before daed child started; launch cancelled" return 0 fi case "$sig" in TERM|INT|QUIT) if [ -z "$shutdown_signal" ]; then shutdown_signal="$sig" shutdown_elapsed=0 fi ;; esac kill -"$sig" "$child_pid" 2>/dev/null } exit_with_signal() { local sig="$1" trap - TERM INT HUP QUIT kill -"$sig" "$$" 2>/dev/null exit 1 } child_is_running() { local state kill -0 "$child_pid" 2>/dev/null || return 1 state=$(awk '{ print $3 }' "/proc/$child_pid/stat" 2>/dev/null) [ "$state" != "Z" ] } trap 'forward_signal TERM' TERM trap 'forward_signal INT' INT trap 'forward_signal HUP' HUP trap 'forward_signal QUIT' QUIT start_child() { local sig # Keep this check inside the function as well as at the call site: # it closes the ordinary pre-start window, while the pending-signal # path below handles a signal arriving during the background fork. [ -z "$pending_signal" ] || return 125 /usr/bin/daed "$@" & child_pid=$! if [ -n "$pending_signal" ]; then sig="$pending_signal" pending_signal= forward_signal "$sig" fi } if [ -n "$pending_signal" ]; then logger -t daed-init "refusing to start daed after pending signal $pending_signal" exit_with_signal "$pending_signal" fi # Best-effort OOM preference; failure must not block startup. if ! echo -16 > /proc/self/oom_score_adj 2>/dev/null; then logger -t daed-init "warn: failed to set /proc/self/oom_score_adj; continuing without OOM preference" fi if ! start_child "$@"; then logger -t daed-init "refusing to start daed after pending signal $pending_signal" if [ -n "$pending_signal" ]; then exit_with_signal "$pending_signal" fi exit 1 fi status=0 reaped=0 while [ "$reaped" -eq 0 ]; do if [ -n "$shutdown_signal" ] && child_is_running; then if [ "$shutdown_elapsed" -ge "$child_term_timeout" ]; then if [ "$forced_kill" -eq 0 ]; then logger -t daed-init "daed did not exit within ${child_term_timeout}s after $shutdown_signal; sending KILL" kill -KILL "$child_pid" 2>/dev/null forced_kill=1 fi else sleep 1 shutdown_elapsed=$((shutdown_elapsed + 1)) continue fi sleep 1 continue fi wait "$child_pid" 2>/dev/null status=$? if ! child_is_running; then reaped=1 fi done child_pid= trap - TERM INT HUP QUIT # Post-exit cleanup runs after the child is reaped. DAED_GUARD_CLEANUP=post-exit cleanup_status=0 daed_cleanup_runtime || cleanup_status=$? if [ "$cleanup_status" -ne 0 ]; then echo "daed: runtime cleanup after exit failed" >&2 logger -t daed-init "post-exit cleanup failed; check ip netns / ip link show" fi if [ "$status" -ne 0 ]; then exit "$status" fi exit "$cleanup_status"