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: Chet Ramey
Subject: Re: variable set in exec'ing shell cannot be unset by child shell
Date: Fri, 13 Oct 2023 17:35:48 -0400
User-agent: Mozilla Thunderbird

On 10/13/23 1:02 PM, Ti Strga 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.

It can, and does, but you're masking the effects of dynamic scoping by
having the same value for different versions of the variable.

For instance, if you were to set OUTSIDE=clone2 before running exec,
you'd see what I mean a little more clearly.

This is what happens. First, you have to remember that variables supplied
as temporary assignments to builtins like eval and source persist for the
entire life of that builtin's execution, and appear in the environment of
child processes those builtins create (this is what the man page text
"added to the environment of the executed command" means for a builtin).

So you have to have a temporary environment for those builtins that
accommodates this, and, similarly to local variables in shell functions,
these temporary variables can shadow global variables.

Here's what that means with the clone2 change, step by step, interspersed
with script output:

1. invocation, OUTSIDE is unset

./outer sanity checking inherited environment, OUTSIDE is

2. outer sources inner.sh with a temporary environment assignment of
   OUTSIDE=clone. This creates a temporary environment with OUTSIDE=clone
   that has priority over global variables and persists for the life of
   `source's execution. No new process is created.

== ./outer beginning sourced file, OUTSIDE is clone and INSIDE is
== ./outer not inside, about to clone

3. inner.sh sets OUTSIDE to clone2 (its copy of the temporary variable,
   more on this later). This affects the temporary environment.

4. inner.sh execs COPY_OF_OUTER with OUTSIDE in its environment with its
   current value (clone2), so COPY_OF_OUTER creates a global shell variable
   from it.

./COPY_OF_OUTER sanity checking inherited environment, OUTSIDE is clone2

5. COPY_OF_OUTER sources inner.sh with a temporary variable assignment to
   OUTSIDE. This overrides the global variable -- which still exists --
   so that inner.sh will see clone as the value of its temporary variable.

./COPY_OF_OUTER beginning sourced file, OUTSIDE is clone and INSIDE is additional data == ./COPY_OF_OUTER inside cloned copy, OUTSIDE is clone and INSIDE is additional data

6. inner.sh calls unset, which unsets the temporary variable (clone) and
   `unshadows' the global variable (clone2)

== ./COPY_OF_OUTER return from unset is 0, now OUTSIDE is clone2 and INSIDE is
== ./COPY_OF_OUTER finishing sourced file, OUTSIDE is clone2 and INSIDE is

7. `source' returns, leaving the global variable intact

./COPY_OF_OUTER having returned from sourcing file, OUTSIDE is clone2

There is code in bash to make a unsetting a function's local copy of a
dynamically-scoped variable that shadows a global variable remain `unset'
instead of unshadowing the global, but I've never done that for source or
eval. It's not clear that would help in this case, either -- it depends
on what the rest of the code does and expects.

Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    chet@case.edu    http://tiswww.cwru.edu/~chet/




reply via email to

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