@@ -1338,6 +1338,7 @@ _comp_variable_assignments()
13381338_comp_finalize__depth= ()
13391339_comp_finalize__target= ()
13401340_comp_finalize__original_return_trap=
1341+ _comp_finalize__original_int_trap=
13411342
13421343# This associative array contains the finalizer commands with the key
13431344# being the name of the completed command.
@@ -1347,6 +1348,28 @@ declare -gA BASH_COMPLETION_FINALIZE_CMD_HOOKS
13471348# executed for all the commands.
13481349declare -g a BASH_COMPLETION_FINALIZE_HOOKS
13491350
1351+ # This array contains the finalizer commands that will be executed for the
1352+ # top-level bash-completion functions. Unlike BASH_COMPLETION_FINALIZE_HOOKS,
1353+ # these hooks are only called at the end of the top-level bash-completion.
1354+ # These hooks are ensured to be called even when the completion is canceled by
1355+ # SIGINT.
1356+ declare -g a BASH_COMPLETION_FINALIZE_TOPLEVEL_HOOKS
1357+
1358+ _comp_finalize__clear ()
1359+ {
1360+ local _hook
1361+ if [[ ${BASH_COMPLETION_FINALIZE_TOPLEVEL_HOOKS[*]+set} ]]; then
1362+ for _hook in " ${BASH_COMPLETION_FINALIZE_TOPLEVEL_HOOKS[@]} " ; do
1363+ eval -- " $_hook "
1364+ done
1365+ fi
1366+ _comp_finalize__depth=()
1367+ _comp_finalize__target=()
1368+ eval -- " ${_comp_finalize__original_int_trap:- trap - INT} "
1369+ eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1370+ _comp_finalize__original_int_trap=
1371+ _comp_finalize__original_return_trap=
1372+ }
13501373_comp_finalize ()
13511374{
13521375 (( ${# _comp_finalize__depth[@]} )) || return 0
@@ -1373,16 +1396,15 @@ _comp_finalize()
13731396 unset -v ' _comp_finalize__depth[${#_comp_finalize__depth[@]}-1]'
13741397 unset -v ' _comp_finalize__target[${#_comp_finalize__target[@]}-1]'
13751398 if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1376- eval -- " ${_comp_finalize__original_return_trap:- trap - RETURN} "
1377- _comp_finalize__original_return_trap=
1399+ _comp_finalize__clear
13781400 break
13791401 fi
13801402 done
13811403}
1382- # Note: We need to set "trace" function attribute of _comp_finalize to
1383- # make the trap restoration by "trap - RETURN" take effect in the
1384- # upper level.
1385- declare -f t _comp_finalize
1404+ # Note: We need to set "trace" function attribute of _comp_finalize{,__clear}
1405+ # to make the trap restoration by "trap - RETURN" take effect in the upper
1406+ # level.
1407+ declare -f t _comp_finalize__clear _comp_finalize
13861408
13871409# Initialize completion and deal with various general things: do file
13881410# and variable completion where appropriate, and adjust prev, words,
@@ -1426,6 +1448,7 @@ _comp_initialize()
14261448 # called for the top-level completion. [ Note: the completion function may
14271449 # be called recursively using "_command_offset", etc. ]
14281450 if (( ${# _comp_finalize__depth[@]} == 0 )) ; then
1451+ _comp_finalize__original_int_trap=$( trap -p INT)
14291452 if shopt -q extdebug || shopt -qo functrace; then
14301453 # If extdebug / functrace is set, we need to explicitly save and
14311454 # restore the original trap handler because the outer trap handlers
@@ -1438,7 +1461,15 @@ _comp_initialize()
14381461 # do not need to explicitly save the outer trap handler.
14391462 _comp_finalize__original_return_trap=
14401463 fi
1464+
1465+ # Note: Ignore the traps previously set by us to avoid infinite
1466+ # loop in case that the previously set traps remain by some
1467+ # accidents.
1468+ _comp_finalize__original_return_trap=${_comp_finalize__original_return_trap## " trap -- '_comp_finalize" * }
1469+ _comp_finalize__original_int_trap=${_comp_finalize__original_int_trap## " trap -- '_comp_finalize" * }
1470+
14411471 trap _comp_finalize RETURN
1472+ trap ' _comp_finalize__clear; kill -INT "$BASHPID"' INT
14421473 fi
14431474 _comp_finalize__depth+=(" ${# FUNCNAME[@]} " )
14441475 _comp_finalize__target+=(" ${FUNCNAME[1]-} " )
0 commit comments