bug-bash
[Top][All Lists]
Advanced

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

Re: forked before bash subshell


From: Greg Wooledge
Subject: Re: forked before bash subshell
Date: Wed, 12 Oct 2016 08:23:37 -0400
User-agent: Mutt/1.4.2.3i

On Tue, Oct 11, 2016 at 07:14:24PM -0700, s7v7nislands@gmail.com 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.

#!/bin/bash
(cd /tmp && exec sleep 20) &
echo "end"

Then, instead of having:

$ ./foo
end
$ ps f -t pts/5
  PID TTY      STAT   TIME COMMAND
 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
end
$ ps f -t pts/5
  PID TTY      STAT   TIME COMMAND
 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]