Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

function in separate process

19 views
Skip to first unread message

John Doe

unread,
Jul 4, 2015, 6:16:43 PM7/4/15
to
I have the following code:

#!/bin/sh
f1 () { /bin/echo "$$: $BASHPID :$a: :$b:" ; return 1; }
f2 () ( /bin/echo "$$: $BASHPID :$a: :$b:" ; return 2; )

a="A"
export b="B"

f1 ; echo $?
f2 ; echo $?

f1 is to be run in current process, f2 is to be run in separate process.
Why does f2 "see" the value of variable a which was not exported? Why is
the difference between execution of f2 in separate process and invoking
shell like this: sh -c '/bin/echo :$a: :$b:' which outputs :: :B: ie.
shell doesn't see the value of unexported a?

What am I missing or misunderstanding? If value of a is substituted
before the process is created for f2 then why is shows different BASHPID
ie. not like the one shown by f1?

John

Janis Papanagnou

unread,
Jul 4, 2015, 6:49:51 PM7/4/15
to
On 05.07.2015 00:16, John Doe wrote:
> I have the following code:
>
> #!/bin/sh
> f1 () { /bin/echo "$$: $BASHPID :$a: :$b:" ; return 1; }
> f2 () ( /bin/echo "$$: $BASHPID :$a: :$b:" ; return 2; )
>
> a="A"
> export b="B"
>
> f1 ; echo $?
> f2 ; echo $?
>
> f1 is to be run in current process, f2 is to be run in separate process. Why
> does f2 "see" the value of variable a which was not exported?

I think that introducing functions in your samples is unnecessary complex to
show what happens WRT exported variables. Inspect the results of...

( /bin/echo "$$: $BASHPID :$a: :$b:" ; exit 3; )
echo $?

sh -c ' /bin/echo "$$: $BASHPID :$a: :$b:" ; exit 4; '
echo $?


Janis

Barry Margolin

unread,
Jul 4, 2015, 8:42:34 PM7/4/15
to
In article <55985b47$0$20132$c3e8da3$1cbc...@news.astraweb.com>,
John Doe <john.doe@notpresent> wrote:

> I have the following code:
>
> #!/bin/sh
> f1 () { /bin/echo "$$: $BASHPID :$a: :$b:" ; return 1; }
> f2 () ( /bin/echo "$$: $BASHPID :$a: :$b:" ; return 2; )
>
> a="A"
> export b="B"
>
> f1 ; echo $?
> f2 ; echo $?
>
> f1 is to be run in current process, f2 is to be run in separate process.
> Why does f2 "see" the value of variable a which was not exported? Why is
> the difference between execution of f2 in separate process and invoking
> shell like this: sh -c '/bin/echo :$a: :$b:' which outputs :: :B: ie.
> shell doesn't see the value of unexported a?

A subshell is a copy of the original shell process, so it has copies of
all its variables. It doesn't exec a new copy of the shell, so you don't
need to export variables to it.

>
> What am I missing or misunderstanding? If value of a is substituted
> before the process is created for f2 then why is shows different BASHPID
> ie. not like the one shown by f1?
>
> John

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

John Doe

unread,
Jul 5, 2015, 4:40:17 AM7/5/15
to
On 05.07.2015 00:49, Janis Papanagnou wrote:
> I think that introducing functions in your samples is unnecessary complex to
> show what happens WRT exported variables. Inspect the results of...
>
> ( /bin/echo "$$: $BASHPID :$a: :$b:" ; exit 3; )
> echo $?
>
> sh -c ' /bin/echo "$$: $BASHPID :$a: :$b:" ; exit 4; '
> echo $?

If sh -c is created as a child process (fork, exec) and inherits only
exported variables, what is the mechanism behind running inside (...)? I
would appreciate some hints about it. At some point, at least for
non-exported variables, it works different...

John

John Doe

unread,
Jul 5, 2015, 4:55:42 AM7/5/15
to
OK, I've found some clue in man ksh: "A parenthesized command is
executed in a sub-shell without removing non-exported variables."

It looks like I need to revisit my understanding of fork, exec,
processess etc.

John

Janis Papanagnou

unread,
Jul 5, 2015, 10:33:44 AM7/5/15
to
On 05.07.2015 10:40, John Doe wrote:
> On 05.07.2015 00:49, Janis Papanagnou wrote:
>> I think that introducing functions in your samples is unnecessary complex to
>> show what happens WRT exported variables. Inspect the results of...
>>
>> ( /bin/echo "$$: $BASHPID :$a: :$b:" ; exit 3; )
>> echo $?
>>
>> sh -c ' /bin/echo "$$: $BASHPID :$a: :$b:" ; exit 4; '
>> echo $?
>
> If sh -c is created as a child process (fork, exec) and inherits only exported
> variables, what is the mechanism behind running inside (...)?

POSIX says: "A subshell environment shall be created as a duplicate of the
shell environment, except that signal traps set by that shell environment
shall be set to the default values."

Janis

John Doe

unread,
Jul 5, 2015, 11:14:36 AM7/5/15
to
On 05.07.2015 16:33, Janis Papanagnou wrote:
> POSIX says: "A subshell environment shall be created as a duplicate of the
> shell environment, except that signal traps set by that shell environment
> shall be set to the default values."

For me a subshell was also a shell invoked by typing sh but it look like
this term is reserved for something slightly different... My bad :(

Is the mechanism behind creating subshell environment generally the same
as for creating an environment for another process (ie. fork -> exec)
but with a few differences (like the one about visibility of
non-exported variables)?

John



Lew Pitcher

unread,
Jul 5, 2015, 11:26:44 AM7/5/15
to
On Sunday July 5 2015 11:14, in comp.unix.shell, "John Doe"
<john.doe@notpresent> wrote:

> On 05.07.2015 16:33, Janis Papanagnou wrote:
>> POSIX says: "A subshell environment shall be created as a duplicate of the
>> shell environment, except that signal traps set by that shell environment
>> shall be set to the default values."
>
> For me a subshell was also a shell invoked by typing sh but it look like
> this term is reserved for something slightly different... My bad :(
>
> Is the mechanism behind creating subshell environment generally the same
> as for creating an environment for another process

Yes, generally

> (ie. fork -> exec)

No.

The main shell will fork(). Now there are two processes both running the same
code. Both processes intepret the same shell code. Each process can determine
(based on the return value from fork() which part of shell script it should
interpret. The main shell will continue on with the main part of the script,
and the child process will interpret the part of the script that is
the "subshell".

So, fork(), but no exec().

> but with a few differences (like the one about visibility of
> non-exported variables)?

That's an inherent consequence of the fork() call.


--
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request

Lew Pitcher

unread,
Jul 5, 2015, 11:30:43 AM7/5/15
to
On Sunday July 5 2015 11:26, in comp.unix.shell, "Lew Pitcher"
<lew.p...@digitalfreehold.ca> wrote:

> On Sunday July 5 2015 11:14, in comp.unix.shell, "John Doe"
> <john.doe@notpresent> wrote:
>
>> On 05.07.2015 16:33, Janis Papanagnou wrote:
>>> POSIX says: "A subshell environment shall be created as a duplicate of the
>>> shell environment, except that signal traps set by that shell environment
>>> shall be set to the default values."
>>
>> For me a subshell was also a shell invoked by typing sh but it look like
>> this term is reserved for something slightly different... My bad :(
>>
>> Is the mechanism behind creating subshell environment generally the same
>> as for creating an environment for another process
[snip]

FWIW, you might take a look at the "Subshells" section of "Advanced Bash
Scripting Guide" at http://www.tldp.org/LDP/abs/html/subshells.html

It has a reasonably non-technical explanation, with example shell code.

Janis Papanagnou

unread,
Jul 5, 2015, 12:51:33 PM7/5/15
to
On 05.07.2015 17:14, John Doe wrote:
> On 05.07.2015 16:33, Janis Papanagnou wrote:
>> POSIX says: "A subshell environment shall be created as a duplicate of the
>> shell environment, except that signal traps set by that shell environment
>> shall be set to the default values."
>
> For me a subshell was also a shell invoked by typing sh [...]

Typing sh invokes (fork-exec's) a command sh, a completely new instance;
this is not different from invoking other [external] commands. The (...)
subshell is a shell "internal" construct (no exec).

Janis

John Doe

unread,
Jul 6, 2015, 3:25:10 PM7/6/15
to
On 05.07.2015 17:26, Lew Pitcher wrote:
> The main shell will fork(). Now there are two processes both running the same
> code. Both processes intepret the same shell code. Each process can determine
> (based on the return value from fork() which part of shell script it should
> interpret. The main shell will continue on with the main part of the script,
> and the child process will interpret the part of the script that is
> the "subshell".
>
> So, fork(), but no exec().
>
>> but with a few differences (like the one about visibility of
>> non-exported variables)?
>
> That's an inherent consequence of the fork() call.

Thank you and thanks to everyone who responded in this thread.

John

0 new messages