I solved in this way:
1. #!/bin/bash
2.
3. set -o errexit
4.
5. function exit_handler ()
6. {
7. local p_lineno="$1"
8.
9. echo "--> ERR HANDLER"
10.
11. for (( i=${#g_bash_lineno[@]}-1; i>=0; i-- ))
12. do
13. test ${g_bash_lineno[$i]} -ne 1 && break
14. done
15.
16. local g_lineno="${g_bash_lineno[$i]}"
17.
18. if test ${p_lineno} -eq 1 && test ${g_lineno} -gt 1
19. then
20. local lineno="${g_lineno}"
21. else
22. local lineno="${p_lineno}"
23. fi
24.
25. local source="${g_bash_source[-1]}"
26.
27. echo "LINENO: ${lineno}"
28. echo "FILE: ${source}"
29.
30. exit
31. }
32. trap 'exit_handler $LINENO' EXIT
33.
34. function preexec ()
35. {
36. local called=$( caller 0 )
37. local lineno=$( echo "$called" | cut -d " " -f1 )
38. local source=$( echo "$called" | cut -d " " -f3 )
39.
40. if ! eval '[[ ${!g_bash_lineno[@]} ]]' # isset
41. then
42. g_bash_lineno=( "$lineno" )
43. else
44. g_bash_lineno=( "${g_bash_lineno[@]}" "$lineno" )
45. fi
46.
47. if ! eval '[[ ${!g_bash_source[@]} ]]' # isset
48. then
49. g_bash_source=( "$source" )
50. else
51. g_bash_source=( "${g_bash_source[@]}" "$source" )
52. fi
53. }
54. trap 'preexec' DEBUG
55.
56. source 'func.sh'
57. testfunc
58.
59. exit 0
The output will be
--> TESTFUNC CALLED
57 main import.sh
now I return a non-zero value
--> ERR HANDLER
LINENO: 57
FILE: main.sh
I followed the suggestion of this question on superuser.
Basically I execute a function (preexec) before any command and I store the information of the caller. When an error occurs I read the information over the last caller if I receive a lineno of 1 in the exit trap (which is always wrong, since the first line of any script should be #!/bin/bash)