[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: variable set in exec'ing shell cannot be unset by child shell
From: |
Kerin Millar |
Subject: |
Re: variable set in exec'ing shell cannot be unset by child shell |
Date: |
Fri, 13 Oct 2023 23:08:08 +0100 |
On Fri, 13 Oct 2023 13:02:30 -0400
Ti Strga <wearyofallthiscrap@gmail.com> wrote:
> First off, I have a feeling that GMail is going to garble the line
> wrapping in this message; I cannot get it to stop being "helpful".
> Apologies if that happens.
>
> I've encountered some behavior that I cannot find described anywhere in
> the man page, and I'm hoping to learn whether it's a bug (it seems like
> unintended behavior) or just a quirk for hysterical raisins. If it's
> the latter then I'm also hoping there's a BASH_COMPAT level that might
> adjust the behavior, although I'll state right now that I have no idea
> whether previous versions behaved any differently.
>
> The summary is that if a parameter is set specifically for a '.'/'source'
> command, and the source'd file calls 'exec' to run another script, then
> that exec'd script cannot unset the parameter; if we want that parameter
> to not be present in the exec'd script, then the source'd file must do
> the unsetting prior to exec.
>
> We're running this...
>
> $ declare -p BASH_VERSINFO
> declare -ar BASH_VERSINFO=([0]="5" [1]="2" [2]="15" [3]="3"
> [4]="release" [5]="x86_64-pc-cygwin")
>
> ...although the platform [5] doesn't seem to matter; the same behavior
> was reported to me on Linux as well as what I'm observing on Cygwin. I
> did not have a chance to verify the Linux behavior firsthand.
>
>
> === Background (or, I Promise This Isn't Just Code Golf)
>
> The example reproduction here is a calling script "outer" sourcing
> "inner.sh". The real world situation is that "inner.sh" is a small
> library of shell functions and environment variable setup for our workflow,
> and multiple top-level scripts each '.' that library.
>
> The games here with exec are to support scripts that might be running for
> a long time. For those we want the script to make a temporary copy of
> itself and exec the temp copy, so that potential updates to the installed
> scripts don't hose up the long-running shell when it suddenly reads from
> a different point in the script.[*] The way it's implemented, the author
> of the top-level script can simply set a parameter when sourcing the
> library; the library makes the copy and performs the exec. When the copy
> sets the same parameter and sources the library, the library detects the
> cloning and will not keep doing it. (The library also fixes up what gets
> reported as "name of current script" for error messages and whatnot, but
> none of that is shown here as it doesn't change the weird behavior.)
>
> [*] Alternatively, there's the trick about putting the entire script
> contents inside a compound statement to force the parser to read it all,
> but that just makes the script harder for a human to read. Copy-and-exec
> makes the top-level scripts cleaner IMHO.
>
> The kicker is that the parameters that trigger all this behavior must be
> unset before going on with the remainder of the library and back to the
> calling script. If not, then anytime a "cloned" script might call any
> other script, that will be cloned as well even if its author did not write
> anything saying to do that. (And in a couple cases, the scripts actually
> start an interactive subshell; if the parameters get exported to there,
> then "CLONE ALL THE THINGS" behavior just keeps propagating through the
> scripts. Hilarity ensues.)
>
>
> === Reproduction
Bash employs dynamic scoping and the behaviour of unset can be confusing in
some cases (with local variables in particular). However, given the code that
you presented, I am unable to reproduce the claimed behaviour in any of 5.1.16,
5.2.15 and the devel branch. In the absence of a minimal reproducible example,
it is difficult to comment. Incidentally, echo is not ideal as a tool for
determining the state of a given variable. Consider "declare -p INSIDE OUTSIDE"
instead.
--
Kerin Millar
- Re: variable set in exec'ing shell cannot be unset by child shell, (continued)
Re: variable set in exec'ing shell cannot be unset by child shell, Grisha Levit, 2023/10/13
Re: variable set in exec'ing shell cannot be unset by child shell,
Kerin Millar <=