tl;dr:bash在调用函数以允许在函数本身而不是其第一个命令上中断时,会额外运行一次调试陷阱。这是源代码的
execute_function
用于调用bash函数:
/* Run the debug trap here so we can trap at the start of a function's
execution rather than the execution of the body's first command. */
震源潜水时间
Here is the code
执行调试陷阱的:
int run_debug_trap () {
(...)
trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
我在那条线上放了一个断点,
trap.c:1081
从今天开始,我们查看了回溯:
初审
Breakpoint 1, run_debug_trap () at trap.c:1081
1081 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
(gdb) where
#0 run_debug_trap () at trap.c:1081
#1 0x000055555559fd3d in execute_simple_command (simple_command=0x5555558aacc8, pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x555555899148) at execute_cmd.c:4056
#2 0x0000555555599fd7 in execute_command_internal (command=0x5555558aae08, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x555555899148) at execute_cmd.c:807
#3 0x00005555555995c1 in execute_command (command=0x5555558aae08) at execute_cmd.c:405
#4 0x0000555555583c9e in reader_loop () at eval.c:180
#5 0x0000555555581794 in main (argc=2, argv=0x7fffffffe4d8, env=0x7fffffffe4f0) at shell.c:792
(gdb) up
#1 0x000055555559fd3d in execute_simple_command (simple_command=0x5555558aacc8, pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x555555899148) at execute_cmd.c:4056
4056 result = run_debug_trap ();
(gdb) print *simple_command->words->word
$3 = {word = 0x5555558a5268 "foo", flags = 0}
换句话说,这是一个简单的命令
foo
. 到现在为止,一直都还不错。
二审
Breakpoint 1, run_debug_trap () at trap.c:1081
1081 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
(gdb) where
#0 run_debug_trap () at trap.c:1081
#1 0x00005555555a170a in execute_function (var=0x5555558ab648, words=0x5555558aac28, flags=0, fds_to_close=0x555555899148, async=0, subshell=0) at execute_cmd.c:4787
#2 0x00005555555a1c68 in execute_builtin_or_function (words=0x5555558aac28, builtin=0x0, var=0x5555558ab648, redirects=0x0, fds_to_close=0x555555899148, flags=0) at execute_cmd.c:5030
#3 0x00005555555a0660 in execute_simple_command (simple_command=0x5555558aacc8, pipe_in=-1, pipe_out=-1, async=0, fds_to_close=0x555555899148) at execute_cmd.c:4330
#4 0x0000555555599fd7 in execute_command_internal (command=0x5555558aae08, asynchronous=0, pipe_in=-1, pipe_out=-1, fds_to_close=0x555555899148) at execute_cmd.c:807
#5 0x00005555555995c1 in execute_command (command=0x5555558aae08) at execute_cmd.c:405
#6 0x0000555555583c9e in reader_loop () at eval.c:180
#7 0x0000555555581794 in main (argc=2, argv=0x7fffffffe4d8, env=0x7fffffffe4f0) at shell.c:792
这更有趣。我们仍在执行简单的命令
福
从以前开始,但它又触发了!为什么呢?让我们看一下呼叫地点,
execute_cmd.c:4787
:
/* Run the debug trap here so we can trap at the start of a function's
execution rather than the execution of the body's first command. */
showing_function_line = 1;
save_current = currently_executing_command;
result = run_debug_trap ();
换句话说,bash似乎有意额外运行一次调试陷阱,目的是破坏一个函数,而不是它的第一个命令。
第三例
不出所料,函数的
echo
命令,所以我不包括它。