@@ -977,6 +977,7 @@ _comp_variable_assignments()
977977_comp_finalize__depth= ()
978978_comp_finalize__target= ()
979979_comp_finalize__original_return_trap=
980+ _comp_finalize__original_int_trap=
980981
981982# This associative array contains the finalizer commands with the key
982983# being the name of the completed command.
@@ -986,6 +987,27 @@ declare -gA BASH_COMPLETION_FINALIZE_CMD_HOOKS
986987# executed for all the commands.
987988declare -g a BASH_COMPLETION_FINALIZE_HOOKS
988989
990+ # This array contains the finalizer commands that will be executed for the
991+ # top-level bash-completion functions. Unlike BASH_COMPLETION_FINALIZE_HOOKS,
992+ # these hooks are only called at the end of the top-level bash-completion.
993+ # These hooks are ensured to be called even when the completion is canceled by
994+ # SIGINT.
995+ declare -g a BASH_COMPLETION_FINALIZE_TOPLEVEL_HOOKS
996+
997+ _comp_finalize__clear ()
998+ {
999+ if [[ ${BASH_COMPLETION_FINALIZE_TOPLEVEL_HOOKS[*]+set} ]]; then
1000+ for _hook in " ${BASH_COMPLETION_FINALIZE_TOPLEVEL_HOOKS[@]} " ; do
1001+ eval -- " $_hook "
1002+ done
1003+ fi
1004+ _comp_finalize__depth=()
1005+ _comp_finalize__target=()
1006+ eval -- " ${_comp_finalize__original_int_trap:- trap - INT} "
1007+ eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1008+ _comp_finalize__original_int_trap=
1009+ _comp_finalize__original_return_trap=
1010+ }
9891011_comp_finalize ()
9901012{
9911013 (( ${# _comp_finalize__depth[@]} )) || return 0
@@ -1012,16 +1034,15 @@ _comp_finalize()
10121034 unset -v ' _comp_finalize__depth[${#_comp_finalize__depth[@]}-1]'
10131035 unset -v ' _comp_finalize__target[${#_comp_finalize__target[@]}-1]'
10141036 if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1015- eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1016- _comp_finalize__original_return_trap=
1037+ _comp_finalize__clear
10171038 break
10181039 fi
10191040 done
10201041}
1021- # Note: We need to set "trace" function attribute of _comp_finalize to
1022- # make the trap restoration by "trap - RETURN" take effect in the
1023- # upper level.
1024- declare -f t _comp_finalize
1042+ # Note: We need to set "trace" function attribute of _comp_finalize{,__clear}
1043+ # to make the trap restoration by "trap - RETURN" take effect in the upper
1044+ # level.
1045+ declare -f t _comp_finalize__clear _comp_finalize
10251046
10261047# Initialize completion and deal with various general things: do file
10271048# and variable completion where appropriate, and adjust prev, words,
@@ -1047,6 +1068,7 @@ _init_completion()
10471068 # called for the top-level completion. [ Note: the completion function may
10481069 # be called recursively using "_command_offset", etc. ]
10491070 if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1071+ _comp_finalize__original_int_trap=$( trap -p INT)
10501072 if shopt -q extdebug || shopt -qo functrace; then
10511073 # If extdebug / functrace is set, we need to explicitly save and
10521074 # restore the original trap handler because the outer trap handlers
@@ -1059,7 +1081,15 @@ _init_completion()
10591081 # do not need to explicitly save the outer trap handler.
10601082 _comp_finalize__original_return_trap=
10611083 fi
1084+
1085+ # Note: Ignore the traps previously set by us to avoid infinite
1086+ # loop in case that the previously set traps remain by some
1087+ # accidents.
1088+ _comp_finalize__original_return_trap=${_comp_finalize__original_int_trap## " trap -- '_comp_finalize" * }
1089+ _comp_finalize__original_int_trap=${_comp_finalize__original_int_trap## " trap -- '_comp_finalize" * }
1090+
10621091 trap _comp_finalize RETURN
1092+ trap ' _comp_finalize__clear; kill -INT "$BASHPID"' INT
10631093 fi
10641094 _comp_finalize__depth+=(" ${# FUNCNAME[@]} " )
10651095 _comp_finalize__target+=(" ${FUNCNAME[1]-} " )
0 commit comments