[Top][All Lists]

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

Re: forked before bash subshell

From: XiaoBing Jiang
Subject: Re: forked before bash subshell
Date: Thu, 13 Oct 2016 09:51:55 +0800

On Wed, Oct 12, 2016 at 8:23 PM, Greg Wooledge <address@hidden> wrote:
On Tue, Oct 11, 2016 at 07:14:24PM -0700, address@hidden wrote:
> why bash bahavior like this? is that a bug?
> if not, why should forked before execute subshell?

Because that's how subshells work.  A subshell *is* a fork.

> 1. the script to reproduce
> bash-4.4$ cat t.sh
> (cd /tmp && sleep 20) &
> echo "end"

When executing the first line:

1) Bash (the parent) forks.
2) The child executes the compound command: cd /tmp && sleep 20
   2a) The child process uses chdir() to change directory.
   2b) The child proesss forks and execs and waits for the external command:
       sleep 20
3) Since the subshell is running in the background, the parent Bash
   continues on to execute: echo "end"
4) The parent Bash exits.  The child which is waiting for sleep 20 to
   terminate continues running.  sleep 20 also continues running.

> 3. script end, but there is a new forked script.
> bash-4.4$ ps -ef | grep t.sh
>   501 50268     1   0 10:09AM ttys015    0:00.00 bash t.sh
>   501 50275 50181   0 10:10AM ttys015    0:00.00 grep t.sh

Process 50268 is the child which is waiting for sleep 20 to finish.

> question:
> when using sh -> dash, It will not fork before subshell, what's the different?

Dash probably optimizes the compound command inside the subshell more
aggressively than bash does.  It may implicitly exec for you.

If you want to ENSURE that the child shell process is replaced by the
external sleep 20, use an explicit exec.

yes, I want to know why bash not optimize this. or any strategy ?

Thank you for your explain!
(cd /tmp && exec sleep 20) &
echo "end"

Then, instead of having:

$ ./foo
$ ps f -t pts/5
 7287 pts/5    Ss     0:00 bash
20165 pts/5    R+     0:00  \_ ps f -t pts/5
20160 pts/5    S      0:00 /bin/bash ./foo
20161 pts/5    S      0:00  \_ sleep 20

You will have:

$ ./foo
$ ps f -t pts/5
 7287 pts/5    Ss     0:00 bash
20173 pts/5    R+     0:00  \_ ps f -t pts/5
20172 pts/5    S      0:00 sleep 20

This is what you wanted, right?

reply via email to

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