# Why does popen3 fork a grandchild?

**URL:** <https://www.ruby-forum.com/t/why-does-popen3-fork-a-grandchild/88878>\
**Category:** Ruby\
**Created:** [March 15, 2007, 8:35am UTC](https://www.ruby-forum.com/t/why-does-popen3-fork-a-grandchild/88878 "2007-03-15T08:35:24Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 15, 2007, 8:35am UTC](https://www.ruby-forum.com/t/why-does-popen3-fork-a-grandchild/88878/1 "2007-03-15T08:35:24Z")

</div>

So I wanted to know why the global variable $? wasn’t being set to  
reflect the exit status of the subprocess when using popen3; I checked  
the list archives and saw that this has come up many times and that  
the cause is that popen3 forks a child, then from the child forks  
another, effectively a “grandchild” process.

One of the consequences is that the exit status is effectively thrown  
away. The workarounds suggested in the archives are:

- don’t use popen3; find an alternative

- instead of checking $? make sure that nothing is printed to the  
standard err

- append the exit code to the standard error as the last line and  
extract it later

- write a popen3 replacement that uses a child rather than a  
grandchild

So I’ve tried the latter option but I’m still left with the  
curiosity… why does popen3 use this child/grandchild model? What are  
the advantages of it?

Cheers,  
Greg

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 16, 2007, 12:46am UTC](https://www.ruby-forum.com/t/why-does-popen3-fork-a-grandchild/88878/2 "2007-03-16T00:46:01Z")

</div>

Greg H. wrote:

> why does popen3 use this child/grandchild model?

It orphans the child process, so its parent doesn’t need to clean  
it up when it dies. Instead, the process is adopted by “init”,  
which is process-id 1, which takes responsibility for the cadaver.

To run completely isolated from the calling process’ environment,  
it must become a leader of a new process group and drop its  
controlling terminal. In BSD-derived system, the latter can be  
done by calling the TIOCNTTY ioctl, and the latter via setgprp().  
On AT&T UNIX systems however, setpgrp performs both functions,  
but only if it’s the first time this call has been made in this  
process. As a result, it must first fork(), then setpgrp(), then  
fork again.

I’m not sure whether all this is completely relevant to popen3,  
but there might be subtle issues on some systems if the code  
was changed to use only one fork. For example, on some Unix  
systems, a terminal (tty) device doesn’t become available until  
the no process has that tty as a controlling tty - so “login”  
can’t issue a login prompt. If you pipe output to a command and  
then exit while it continues to process that data, then the user  
logs out, no-one won’t be able to log in again on that tty until  
the background process exits.

All this was thoroughly examined by Dave Lennert in his classic  
1987 posting entitled “How to write a Unix Daemon” to the HP  
internal newsgroup “hp.unix”, which I archived and still have.  
The paper was also published in “;login:”, Volume 12 No 4,  
July/August 1987. The paper seems rather hard to find online now.

Clifford H…

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 16, 2007, 1:26am UTC](https://www.ruby-forum.com/t/why-does-popen3-fork-a-grandchild/88878/3 "2007-03-16T01:26:04Z")

</div>

On Fri, 16 Mar 2007, Clifford H. wrote:

> It orphans the child process, so its parent doesn’t need to clean  
> it up when it dies. Instead, the process is adopted by “init”,  
> which is process-id 1, which takes responsibility for the cadaver.

Thanks for the substantive reply, saves me the bother of doing a  
poorer one…

> All this was thoroughly examined by Dave Lennert in his classic  
> 1987 posting entitled “How to write a Unix Daemon” to the HP  
> internal newsgroup “hp.unix”, which I archived and still have.  
> The paper was also published in “;login:”, Volume 12 No 4,  
> July/August 1987. The paper seems rather hard to find online now.

Can you post a link, or email me a copy?

Thanks

John C. Phone : (64)(3) 358 6639  
Tait Electronics Fax : (64)(3) 359 4632  
PO Box 1645 Christchurch Email : removed\_email\_address@domain.invalid  
New Zealand

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 16, 2007, 8:12am UTC](https://www.ruby-forum.com/t/why-does-popen3-fork-a-grandchild/88878/4 "2007-03-16T08:12:31Z")

</div>

John C. wrote:

> Can you post a link, or email me a copy?

[http://cjh.polyplex.org/software/daemon.pdf](http://cjh.polyplex.org/software/daemon.pdf)

I had to dig up the “mm” macros, then groff to ps, then ps2pdf 🙂  
There seem to be unnecessary page breaks, but I didn’t change  
Dave Lennert’s source.

Clifford H…

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 16, 2007, 10:45pm UTC](https://www.ruby-forum.com/t/why-does-popen3-fork-a-grandchild/88878/5 "2007-03-16T22:45:52Z")

</div>

Greg H. wrote:

> Many thanks for sharing this, Clifford!

You’re welcome. I always thought it was a “keeper”.

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 16, 2007, 1:27pm UTC](https://www.ruby-forum.com/t/why-does-popen3-fork-a-grandchild/88878/6 "2007-03-16T13:27:11Z")

</div>

On 16 mar, 08:08, Clifford H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I had to dig up the “mm” macros, then groff to ps, then ps2pdf 🙂  
> There seem to be unnecessary page breaks, but I didn’t change  
> Dave Lennert’s source.

Many thanks for sharing this, Clifford!

Cheers,  
Greg
