|
From: R. B. <ro...@pa...> - 2003-04-01 06:38:42
|
Chet Ramey writes:
> The integration of your patches to the mainline bash code is complete. The
> result passes all of the tests added to the bash suite, with a single
> exception. The primary difference is:
Many thanks for integrating the debugging support patches into the
mainline bash code. I look forward to the day when the sourceforge
copy can be removed!
> The primary difference is:
>
> 1. The RETURN trap is executed whenever a script run with `.' or `source'
> finishes, not just when it calls `return'.
This is an improvement and an oversight or coding inexperience on my
part.
>
> (This mirrors the behavior of shell functions.)
Great!
>
> I have a couple of questions for discussion:
>
> 1. Why do scripts executed with `.' or `source' inherit the RETURN trap?
> Shell functions don't.
>
> 2. Why do command substitutions inherit the RETURN trap?
>
The code that implements this policy, I think, is this code in
execute_cmd.c:
/*
Reset debug, error and return trap handlers. Set up to
restore them on return.
....
return_trap = TRAP_STRING(RETURN_TRAP);
if (return_trap)
...
versus this code in trap.c:
/* Command substitution and other child processes don't inherit the
debug or error traps. */
if (!function_trace_mode)
sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
I envisioned the RETURN trap for two purposes. The first was to be able
to implement a gdb "finish" command. (Since gdb's "return" command
means something else, the name RETURN might be confusing here. I
really don't know).
Here, the RETURN trap I think should mimic behavior of "set -o
fntrace" (or variable function_trace_mode). That is, when one requests
the facility to debug into a function, with that should also get the
ability to catch an an exit out of that function. Assuming that
philosophy, the code cited above for execute_cmd.c is flawed and
should be:
if (!function_trace_mode && return_trap)
The second intended use for the RETURN trap was precisely to catch a
subshell exit.
Some background. A debugger such as this one lives inside the
environment of the debugged program. But one would like to think of
the global debugger state (such as breakpoints and debugger settings)
as being outside and independent of the debugged program. There is a
problem in passing state or part of the environment from a nested bash
session (SHLVL) or a subshell out to the parent environment.
In a sense I think of this as a general POSIX shell problem. There's
an "export" command to the child but no "export" to parent.
In order to simulate "export to parent", currently the bash debugger
has to do this in a very inefficient way. Any variable that is to be
exported to the parent is written to a journal file. The file may
contain the entire history of the changes of that variable. For
example x=1; ... x=2; ... unset x; ... x=3.
In fact, the only relevant value is the last one set/unset. Every time
DEBUG trap is called, we have to source in that journal (if it
exists); the only time it can be removed and can stop recording
changes to the journal is when we get back to the initial SHLVL and
there are no subshells.
Okay. Sorry for the long-winded background. We finally get to that
second use and what a trap RETURN routine could do to help the
export-to-parent problem.
It would be best to have two trap calls. Just before the exit,
variables marked "export" would be saved. And just after the exit, the
parent would read in those saved values. Even if you have only one
call it'd still save a bit of the unnecessary work. If I had a return
in the child, rather than saving the entire history of value changes,
I might be able to just save the last value of the marked
variables. (I'd still have to have a list of marked variables). If I
had a RETURN trap call in the parent, I would only have to read in
this journal file once, even though the file might contain overwritten
variable assignments.
> Thanks for all your hard work.
My pleasure and even more thanks thanks for all of *your* hard work!
|