bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

issues with SHLVL, subshells and implicit "exec"s


From: Stephane Chazelas
Subject: issues with SHLVL, subshells and implicit "exec"s
Date: Sat, 3 Sep 2016 17:08:12 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

Hello,

that came up when discussing a related bug in zsh
(http://www.zsh.org/mla/workers/2016/msg01574.html)

$SHLVL is a feature introduced by tcsh (at least some patches on
tcsh) in the early eighties, that is meant to represent the
depth of a stack of shells executing each other.

It's not POSIX, but it's supported by tcsh, bash, zsh, ksh93
and busybox sh at least.

It's not incremented for subshells, only for shell invocations.

Where the behaviour differs is when using "exec".

All of tcsh, bash and zsh (but not ksh93 nor busybox sh)
decrement SHLVL when a "exec" would replace the shell process
with another command.

That makes sense because in

bash(1)
 |
 `- bash(2)
     |
     `- bash(3) -c 'exec bash(4)'

for instance, that bash(4) will end up being the child of
bash(2), just like bash(3). So bash(3) decrements SHLVL before
invoking bash(4), which will increment it again.

Now, and it's my first bug.

In:

$ echo "$SHLVL $$"
2 6192
$ bash -c bash
$ echo "$SHLVL $$ $PPID"
4 6193 6192

SHLVL has been increased by *2* even though that new bash shell
is a direct child of the previous one. That's because that "bash
-c bash" is actually a "bash -c 'exec bash'". That is bash
optimises out the fork for the execution of that one command.
While SHLVL is decremented for an explicit "exec", it is not for
an implicit one which IMO is a bug

Second bug:

$ SHLVL=1 bash -c 'echo "$SHLVL"; (exec bash); echo done'
2
$ echo "$SHLVL"
2
$ exit
done

There, bash has decremented $SHLVL upon "exec bash" even though
it was in a subshell. So the new bash shell ended up with the same
SHLVL as its parent.

tcsh has the same bug.

(tested with the head of the "devel" git branch)

-- 
Stephane



reply via email to

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