@@ -1488,6 +1488,7 @@ _comp_variable_assignments()
14881488_comp_finalize__depth= ()
14891489_comp_finalize__target= ()
14901490_comp_finalize__original_return_trap=
1491+ _comp_finalize__original_int_trap=
14911492
14921493# This associative array contains the finalizer commands with the key
14931494# being the name of the completed command.
@@ -1497,6 +1498,28 @@ declare -gA BASH_COMPLETION_FINALIZE_CMD_HOOKS
14971498# executed for all the commands.
14981499declare -g a BASH_COMPLETION_FINALIZE_HOOKS
14991500
1501+ # This array contains the finalizer commands that will be executed for the
1502+ # top-level bash-completion functions. Unlike BASH_COMPLETION_FINALIZE_HOOKS,
1503+ # these hooks are only called at the end of the top-level bash-completion.
1504+ # These hooks are ensured to be called even when the completion is canceled by
1505+ # SIGINT.
1506+ declare -g a BASH_COMPLETION_FINALIZE_TOPLEVEL_HOOKS
1507+
1508+ _comp_finalize__clear ()
1509+ {
1510+ local _hook
1511+ if [[ ${BASH_COMPLETION_FINALIZE_TOPLEVEL_HOOKS[*]+set} ]]; then
1512+ for _hook in " ${BASH_COMPLETION_FINALIZE_TOPLEVEL_HOOKS[@]} " ; do
1513+ eval -- " $_hook "
1514+ done
1515+ fi
1516+ _comp_finalize__depth=()
1517+ _comp_finalize__target=()
1518+ eval -- " ${_comp_finalize__original_int_trap:- trap - INT} "
1519+ eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1520+ _comp_finalize__original_int_trap=
1521+ _comp_finalize__original_return_trap=
1522+ }
15001523_comp_finalize ()
15011524{
15021525 (( ${# _comp_finalize__depth[@]} )) || return 0
@@ -1523,16 +1546,15 @@ _comp_finalize()
15231546 unset -v ' _comp_finalize__depth[${#_comp_finalize__depth[@]}-1]'
15241547 unset -v ' _comp_finalize__target[${#_comp_finalize__target[@]}-1]'
15251548 if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1526- eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1527- _comp_finalize__original_return_trap=
1549+ _comp_finalize__clear
15281550 break
15291551 fi
15301552 done
15311553}
1532- # Note: We need to set "trace" function attribute of _comp_finalize to
1533- # make the trap restoration by "trap - RETURN" take effect in the
1534- # upper level.
1535- declare -f t _comp_finalize
1554+ # Note: We need to set "trace" function attribute of _comp_finalize{,__clear}
1555+ # to make the trap restoration by "trap - RETURN" take effect in the upper
1556+ # level.
1557+ declare -f t _comp_finalize__clear _comp_finalize
15361558
15371559# Initialize completion and deal with various general things: do file
15381560# and variable completion where appropriate, and adjust prev, words,
@@ -1576,6 +1598,7 @@ _comp_initialize()
15761598 # called for the top-level completion. [ Note: the completion function may
15771599 # be called recursively using "_command_offset", etc. ]
15781600 if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1601+ _comp_finalize__original_int_trap=$( trap -p INT)
15791602 if shopt -q extdebug || shopt -qo functrace; then
15801603 # If extdebug / functrace is set, we need to explicitly save and
15811604 # restore the original trap handler because the outer trap handlers
@@ -1588,7 +1611,15 @@ _comp_initialize()
15881611 # do not need to explicitly save the outer trap handler.
15891612 _comp_finalize__original_return_trap=
15901613 fi
1614+
1615+ # Note: Ignore the traps previously set by us to avoid infinite
1616+ # loop in case that the previously set traps remain by some
1617+ # accidents.
1618+ _comp_finalize__original_return_trap=${_comp_finalize__original_return_trap## " trap -- '_comp_finalize" * }
1619+ _comp_finalize__original_int_trap=${_comp_finalize__original_int_trap## " trap -- '_comp_finalize" * }
1620+
15911621 trap _comp_finalize RETURN
1622+ trap ' _comp_finalize__clear; kill -INT "$BASHPID"' INT
15921623 fi
15931624 _comp_finalize__depth+=(" ${# FUNCNAME[@]} " )
15941625 _comp_finalize__target+=(" ${FUNCNAME[1]-} " )
0 commit comments