Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64'
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-unknown-linux-gnu'
-DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/local/share/locale'
-DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib
-g -O2 -Wno-parentheses -Wno-format-security
uname output: Linux xanadu 4.4.0-103-lowlatency #126-Ubuntu SMP PREEMPT
Mon Dec 4 17:15:55 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-unknown-linux-gnu
Bash Version: 4.4
Patch Level: 12
Release Status: release
Description:
When a function looks like it is defined in multiple sources,
BASH_SOURCE does not reliably report it has defined
where it was actually defined. It seems to prefer the
last source bash has visited.
This is not related to a multiple definition. When I
say 'looks like', it actually 'looks like' from an
external point of view, but it does not from a
runtime point of view.
Running the attached example, we get:
$ ./bash-4.4.12 call-stack.sh
1 def-2.sh:5 def-1.sh x_trace_stack
1 def-2.sh:5 def-2.sh x_trace_stack
The cells 'def-2.sh:5' are build from BASH_SOURCE and
BASH_LINENO. They should report in order:
def-1.sh:5
def-2.sh:5
but the first one is wrong. Note that BASH_LINENO is correct,
and this is unlikely due to chance.
Repeat-By:
Here are three scripts:
- call-stack.sh
- def-1.sh
- def-2.sh
Both def-1.sh and def-2.sh /may/ define functions 'def1'
and 'def2',
but actually def-1.sh defines 'def1' while def-2.sh
defines 'def2',
as those functions do report themselves.
Sourcing call-stack.sh, we observe that both 'def1' and
'def2' are reported by BASH_SOURCE to be defined in def-2.sh.
Scripts:
# ---------------------------------------------------------
# call-stack.sh
#!/bin/bash
x_trace_stack() { # [MESSAGE START STOP] # Dump call stack #1
# START STOP unused
local -i i=1
local ONCE="$1"; shift
printf "%d %15s:%-3s %8s %s\n" \
$i \
"${BASH_SOURCE[i]}" \
"${BASH_LINENO[i-1]}" \
"$ONCE" \
"${FUNCNAME[i-1]}"
}
. def-1.sh
. def-2.sh
def1
def2
# ------------------------------------------------------------
# def-1.sh
#!/bin/bash
_() { [ $1 = def1 ]; }
_ def1 && def1() { x_trace_stack def-1.sh 1 2; }
_ def2 && def2() { x_trace_stack def-1.sh 1 2; }
# ------------------------------------------------------------
# def-2.sh
#!/bin/bash
_() { [ $1 = def2 ]; }
_ def2 && def2() { x_trace_stack def-2.sh 1 2; }
_ def1 && def1() { x_trace_stack def-2.sh 1 2; }