Menu

[69de4e]: / lib / sig.sh  Maximize  Restore  History

Download this file

279 lines (234 with data), 8.7 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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# -*- shell-script -*-
# Signal handling routines
#
# Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008, 2010, 2011, 2017
# Rocky Bernstein <rocky@gnu.org>
#
# This program 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 2, or
# (at your option) any later version.
#
# This program 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 this program; see the file COPYING. If not, write to
# the Free Software Foundation, 59 Temple Place, Suite 330, Boston,
# MA 02111 USA.
# ==================== VARIABLES =======================================
# The "set" options in effect ($-) before debugger was invoked.
typeset _Dbg_old_setopts
# Place to save debugged program's exit handler, if any.
typeset _Dbg_old_EXIT_handler=''
typeset -i _Dbg_QUIT_ON_QUIT=0
# Return code that debugged program reports
typeset -i _Dbg_program_exit_code=0
############################################################
## Signal arrays: These are indexed by the signal number. ##
############################################################
# Should we print that a signal was intercepted?
# Each entry is "print" or "noprint" or null.
typeset -a _Dbg_sig_print; _Dbg_sig_print=()
# Should we reentry the debugger command loop on receiving the signal?
# Each entry is "stop" or "nostop" or null.
typeset -a _Dbg_sig_stop; _Dbg_sig_stop=()
# Should we show a traceback on receiving the signal?
# Each entry is "stack" or "nostack" or null.
typeset -a _Dbg_sig_show_stack; _Dbg_sig_show_stack=()
# Should pass the signal to the user program??
# Each entry is the trap handler with some variables substituted.
typeset -a _Dbg_sig_passthrough; _Dbg_sig_passthrough=()
# Should pass the signal to the user program??
# Each entry is the trap handler with some variables substituted.
typeset -i _Dbg_return_level=0
# Place to save values of $1, $2, etc.
typeset -a _Dbg_arg; _Dbg_arg=()
# Save value of handler variable _Dbg_old_$sig
_Dbg_save_handler() {
typeset -r sig=$1
typeset old_handler=''
old_handler_test=$(trap -p $sig)
if [[ -n $old_handler ]] ; then
typeset -a old_hand_a
old_hand_a=($old_handler)
old_handler=$(_Dbg_subst_handler_var ${old_hand_a[2]})
typeset -r decl_cmd="typeset -r _Dbg_old_${sig}_handler='$old_handler'"
eval $decl_cmd
fi
}
# Adjust handler variables to take into account the fact that when we
# call the handler we will have added another call before the user's
# handler.
_Dbg_subst_handler_var() {
typeset -i i
typeset result=''
for arg in $* ; do
case $arg in
'$LINENO' )
arg='${BASH_LINENO[0]}'
;;
'${BASH_SOURCE[0]}' )
arg='${BASH_SOURCE[1]}'
;;
'${FUNCNAME[0]}' )
arg='${FUNCNAME[1]}'
;;
'${BASH_LINENO[0]}' )
arg='${BASH_LINENO[1]}'
;;
esac
if [[ $result == '' ]] ; then
result=$arg
else
result="$result $arg"
fi
done
echo $result
}
# Debugger exit handler. Don't really exit - but go back the debugger
# command loop
_Dbg_exit_handler() {
# Consider putting the following line(s) in a routine.
# Ditto for the restore environment
typeset -i _Dbg_debugged_exit_code=$?
# Turn off line and variable trace listing; allow unset parameter expansion.
set +x +v +u +e
if [[ ${_Dbg_sig_print[0]} == "print" ]] ; then
# Note: use the same message that gdb does for this.
_Dbg_msg "Program received signal EXIT (0)..."
if [[ ${_Dbg_sig_show_stack[0]} == "showstack" ]] ; then
_Dbg_do_backtrace 0
fi
fi
if [[ $_Dbg_old_EXIT_handler != '' ]] ; then
eval $_Dbg_old_EXIT_handler
fi
# If we've set the QUIT signal handler not to stop, or we've in the
# middle of leaving so many (subshell) levels or we have set to
# leave quietly on termination, then do it!
if [[ ${_Dbg_sig_stop[0]} != "stop" ]] \
|| (( _Dbg_QUIT_LEVELS != 0 )) \
|| (( _Dbg_QUIT_ON_QUIT )) ; then
_Dbg_do_quit
# We don't return from here.
fi
# We've tested for all the quitting conditions above.
# Even though this is an exit handler, don't exit!
typeset term_msg="normally"
if [[ $_Dbg_debugged_exit_code != 0 ]] ; then
term_msg="with code $_Dbg_debugged_exit_code"
fi
# If we tried to exit from inside a subshell, we only want to enter
# the command loop if don't have any pending subshells.
if (( BASH_SUBSHELL == 0 )) ; then
_Dbg_msg \
"Debugged program terminated $term_msg. Use q to quit or R to restart."
_Dbg_running=0
while : ; do
_Dbg_process_commands
done
fi
}
# Generic signal handler. We consult global array _Dbg_sig_* for how
# to handle this signal.
# Since the command loop may be called we need to be careful about
# using variable names that would be exposed to the user.
_Dbg_sig_handler() {
# Consider putting the following line(s) in a routine.
# Ditto for the restore environment
typeset -i _Dbg_debugged_exit_code=$?
_Dbg_old_set_opts=$-
# Turn off line and variable trace listing if were not in our own debug
# mode, and set our own PS4 for debugging inside the debugger
(( !_Dbg_set_debug )) && set +x +v +u
shopt -s extdebug
# This is the signal number. E.g. 15 is SIGTERM
typeset -r -i _Dbg_signum=$1
if [[ ${_Dbg_sig_print[$_Dbg_signum]} == "print" ]] || \
[[ ${_Dbg_sig_stop[$_Dbg_signum]} == "stop" ]] ; then
typeset -r name=$(_Dbg_signum2name $_Dbg_signum)
# Note: use the same message that gdb does for this.
_Dbg_msg "Program received signal $name ($_Dbg_signum)..."
if [[ ${_Dbg_sig_show_stack[$_Dbg_signum]} == "showstack" ]] ; then
_Dbg_stack_pos=0
((_Dbg_stack_size = ${#FUNCNAME[@]}))
_Dbg_do_backtrace
fi
fi
if [[ ${_Dbg_sig_stop[$_Dbg_signum]} == "stop" ]] ; then
### The below duplicates what is above in _Dbg_debug_trap handler
### Should put common stuff into a function.
shift # signum
_Dbg_save_args "$@"
_Dbg_set_debugger_entry
_Dbg_hook_enter_debugger 'on receiving a signal' 'noprint'
return $_Dbg_continue_rc
elif (( _Dbg_sig_old_handler[_Dbg_signum] )) ; then
eval ${_Dbg_sig_old_handler[$_Dbg_signum]}
fi
_Dbg_set_to_return_from_debugger 1
return $_Dbg_debugged_exit_code
}
_Dbg_err_handler() {
if [[ $_Dbg_old_ERR_handler != '' ]] ; then
eval $_Dbg_old_ERR_handler
fi
_Dbg_msg "Error occured at ${BASH_SOURCE[1]}:${BASH_LINENO[1]}"
_Dbg_process_commands
}
# Echo the name for a given signal number $1. The resulting name
# is in _Dbg_return
_Dbg_signum2name() {
typeset -i -r signum=$1;
builtin kill -l $signum 2>/dev/null
return $?
}
# Return the signal number for a given signal name $1. The resulting number
# is in _Dbg_return
_Dbg_name2signum() {
typeset -r signame=$1;
builtin kill -l $signame 2>/dev/null
return $?
}
_Dbg_subexit_handler() {
# Read in the journal to pick up variable settings that might have
# been left from a subshell.
if [[ ${FUNCNAME[1]} == _Dbg_* ]] && (( !_Dbg_set_debug )); then
return 0
fi
_Dbg_source_journal
if (( _Dbg_QUIT_LEVELS > 0 )) ; then
_Dbg_do_quit $_Dbg_debugged_exit_code
fi
}
# Set up generic trap handler. Arguments are:
# NAME print showstack stop passthrough
_Dbg_init_trap() {
typeset -r name=$1
typeset -i -r signum=$(_Dbg_name2signum $name)
_Dbg_sig_print[$signum]=$2;
_Dbg_sig_show_stack[$signum]=$3;
_Dbg_sig_stop[$signum]=$4;
# Work out passthrough later...
# if [[ $5 == "pass*" ]] ; then
# get existing trap from env.
# _Dbg_sig_show_passthrough[$signum]=....;
#
if (( signum == 0 )) ; then
trap '_Dbg_exit_handler "$BASH_COMMAND"' EXIT
else
typeset trap_cmd="trap '_Dbg_sig_handler $signum \"\$BASH_COMMAND\" \"\$@\"' $name"
eval $trap_cmd
fi
}
_Dbg_init_default_traps() {
_Dbg_init_trap EXIT "noprint" "nostack" "stop"
_Dbg_init_trap ILL "print" "showstack" "stop"
_Dbg_init_trap INT "print" "showstack" "stop"
_Dbg_init_trap QUIT "print" "showstack" "stop"
_Dbg_init_trap TERM "print" "showstack" "stop"
_Dbg_init_trap TRAP "print" "showstack" "stop"
}
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.