bug-bash
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]