Glad I could be of assistance!
Regarding your question, the magic occurs in the first line of
run_shell. When open is called with
"-|" as its file argument, it does something special:
It forks the current process into two processes (parent and child)
that run in parallel.
The parent process is the same as the original process. It
receives in $pid the child's process ID, and its
$pipe variable contains a filehandle that can read from
the STDOUT of the child process.
The child process – and this is where it gets interesting
– is running in parallel to the parent. The only difference is
that in the child, the pid returned from open and stored
in its copy of $pid is zero.
So now we have the parent and the child running in parallel. The
first thing they both do is check the value of $pid to
figure out which is parent and which is child. If $pid
non-zero, the one process then knows that it is the parent, and it can
package up the information it received about the child from
open and return the package to the original caller. If
$pid is zero, the other process knows it is the child and
then ties its STDOUT to STDERR, starts a new
process group, and then uses exec to replace its own
process image with that of the command we gave to
run_shell as arguments.
Thus, when run_shell returns, we have the following
situation:
- The original process has become a parent, and it continues running
on the line after the call to run_shell. It holds in its
variable $subshell the pid of its new child and a pipe to
read output from the child. The parent also knows that there is a
process group of the same ID as the child's pid, and that all of the
child's descendants will belong to it.
- The child process has now been taken over by the command that we wanted
to be executed. The new command, however, is running in the
environment that we set up earlier, while we had control of the
child. Thus its STDERR is tied to its STDOUT, and it is running in a
process group that the child set up and that the parent knows about.
I hope that explanation clears things up.
Cheers, Tom
| [reply] [d/l] [select] |