-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexception_handling_core.sh
More file actions
executable file
·159 lines (126 loc) · 5.09 KB
/
Copy pathexception_handling_core.sh
File metadata and controls
executable file
·159 lines (126 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/bin/bash
# ==============================================================================
# MODULE: exception_handling_core.sh
# DESCRIPTION: Multi-process exception engine with auto-recovery and data passing.
# ==============================================================================
# --- 1. ENGINE SETTINGS (Adaptive) ---
set -E
set -o errtrace
# Probe for inherit_errexit support without triggering errors
HAS_INHERIT_ERREXIT=false
if set -o inherit_errexit 2>/dev/null; then
HAS_INHERIT_ERREXIT=true
fi
# --- 2. STATE STORAGE ---
declare -A HANDLERS
export HANDLER_ARGS=()
# --- 3. HELP SYSTEM ---
exception_handler_help() {
# Using 'EOF' in quotes makes the text 100% literal (no accidental execution)
cat << 'EOF'
Exception handler Usage:
register_handler [-f] <CONTEXT> <FUNCTION_NAME>
- Register a repair function for a specific error context.
- Use -f to force overwrite an existing registration.
throw_exception <CONTEXT> [EXIT_CODE] [ARGS...]
- Triggers the ERR trap and jumps to the registered handler.
- Exit code defaults to 1. Extra args passed to handler as $4, $5, etc.
dispatch_exception (Internal)
- The trap runner. Returns 0 to resume worker at the next line.
EOF
if [ "$HAS_INHERIT_ERREXIT" = false ]; then
cat << 'EOF'
Warning: inherit_errexit is NOT supported by this Bash binary.
Manual throw is required for command substitutions.
Fails silently on this machine: data=$(some_broken_command)
Works on this machine: data=$(some_broken_command) || throw_exception "ERR" "msg"
EOF
fi
}
# --- 4. DEFAULT HANDLER ---
default_handler() {
local context="$1"
local exit_code="$2"
local failed_cmd="$3"
echo -e "\n--------------------------------------------------------" >&2
[[ "$context" != "DEFAULT" ]] && echo -e "handler not found for $context, Default handler Entered" >&2
echo "--------------------------------------------------------" >&2
echo "🚨 EXCEPTION TRIGGERED" >&2
echo "Context: $context" >&2
echo "Exit Code: $exit_code" >&2
echo "Command: $failed_cmd" >&2
echo "Arguments: ${HANDLER_ARGS[*]}" >&2
echo "--------------------------------------------------------" >&2
echo "TRACEBACK (Most recent call last):" >&2
# We start at 1 to skip the 'dispatch_exception' and 'default_handler' themselves
for ((i=1; i<${#FUNCNAME[@]}; i++)); do
local func="${FUNCNAME[$i]}"
local file="${BASH_SOURCE[$i]}"
local line="${BASH_LINENO[$((i-1))]}" # Line where the call happened
# Skip internal Bash top-level call "main" if you prefer
#[[ "$func" == "main" && "$file" == "$0" ]] && func="[Script Top Level]"
printf " File \"%s\", line %d, in %s\n" "$file" "$line" "$func" >&2
done
echo "--------------------------------------------------------" >&2
# Cleanup and exit as before
HANDLER_ARGS=()
export CURRENT_CONTEXT="DEFAULT"
echo "exiting with code: $exit_code" >&2
exit "$exit_code"
}
# --- 5. UNIFIED THROWER ---
throw_exception() {
local custom_code=1
local context="$1"
[[ -z "$context" ]] && { echo "[throw_exception error] Context name required"; return 1; }
if [[ "$2" =~ ^[0-9]+$ ]]; then
custom_code="$2"
shift 2
else
shift 1
fi
export CURRENT_CONTEXT="$context"
HANDLER_ARGS=("$@")
#echo ">>> [THROW EXCEPTION] Context: $context, Exit Code: $custom_code" >&2
# 1. Force the dispatch immediately, bypassing Bash's ERR trap suppression
dispatch_exception "$custom_code"
# 2. If the handler successfully repairs and allows continuation, return the code
return "$?"
}
# --- 6. REGISTRATION ---
register_handler() {
local force=false
[[ "$1" == "-f" ]] && { force=true; shift; }
local context="$1"
local handler_cmd="$2"
[[ -z "$context" || -z "$handler_cmd" ]] && return 1
[[ -n "${HANDLERS[$context]}" && "$force" == false ]] && return 1
! type "$handler_cmd" > /dev/null 2>&1 && return 1
HANDLERS["$context"]="$handler_cmd"
}
# --- 7. SMART DISPATCH ENGINE ---
dispatch_exception() {
# If $1 is provided (manual throw), use it. Otherwise, use $? (auto trap).
local exit_code="${1:-$?}"
local failed_cmd="$BASH_COMMAND"
local context="${CURRENT_CONTEXT:-DEFAULT}"
local repair_func="${HANDLERS[$context]:-default_handler}"
#echo ">>> [DISPATCH EXCEPTION] Context: $context, Command: $failed_cmd" >&2
"$repair_func" "$context" "$exit_code" "$failed_cmd" "${HANDLER_ARGS[@]}"
local handler_status=$?
HANDLER_ARGS=()
export CURRENT_CONTEXT="DEFAULT"
if [[ $handler_status -ne 0 ]]; then
echo ">>> [ERROR] Handler for context '$context' failed with exit code $handler_status. Terminating." >&2
exit "$handler_status"
fi
return 0
}
# --- 8. INITIALIZATION ---
trap 'dispatch_exception' ERR
register_handler "DEFAULT" "default_handler"
# Show help only if the script is executed directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
echo "[Exception Handler Ready] Bash $BASH_VERSION detected."
exception_handler_help
fi