From: sgr@alden.UUCP (Stan Ryckman)
Newsgroups: comp.unix.wizards
Subject: Re: fork() and forget..How?
Keywords: fork() wait() getpid() getppid()
Date: 9 Oct 92 16:49:54 GMT
Organization: Alden Electronics, Westboro, MA

In article <1992Oct07.194020.14527@ctms.gwinnett.com> kirk@ctms.gwinnett.com (R. Kirk Waterhouse) writes:
>
>I am looking for a way to fork() a process and forget about it.
>
>Here is the scenario: 
>
>I have a process that is constantly reading data from another process.
>My process has been popen()'ed from this other process, so I have the 5120 byte
>buffer from the pipe which allows me to do the necessary processing on the data.
>My process is basicly queing up data to send to another process. 
>
>This other process is my problem.
>
>I need to have multiple instantiations of this process running in the backgroundto act as multiple channels. However, I want to send a batch of data to this 
>other process, allow it to process this batch and die off when through, while my
>current process is still recieving data from the process that is feeding it.
>
>Wow!, did I say that right?  Yea, see picture below.
>
>-----------     P      ----------- fork()---> Channel 3 }  These are not so much
>|  Main   | --->I      |   My    | fork()---> Channel 2 }  channels, as they are
>| Process |     P ---> | Process | fork()---> Channel 4 }  independtly running
>-----------     E      ----------- fork()---> Channel 1 }  processes that die
>                                   fork()---> Channel x }  when complete.
>
>I followed the examples in the AT&T Programmers Guide and other books and they 
>won't quite work.

[...deleted...]

>If I do it basicly like this I only get one instantiation of my child process
>because the parent sits there at the wait, losing data from it's input because
>this child takes approx. 1-2 minutes to complete.
>
>If I leave out the wait, I get hundreds of instantiations of my child process
>which become zombie processes with a parent of (1 or init) until I can issue
>a wait().  (When could I issue a wait()?)  At this point I loose data again from
>my input process until all of these zombie processes get cleared up. (If I do 
>not issue the wait or kill my process, I soon cannot fork() anymore, I guess I 
>am exceeding the maxixmum number of processes) 
>
>Any body got any ideas? This is the first time I have used fork(), is there
>something basic I am missing?
>
>At this point (until I figure out the fork()'s) I am just running my child 
>process in the background and opening up an IPC FIFO between us and having to 
>know in advance how many channels I will need so I can open up that many FIFOs.

[...deleted...]

>Any insight to this problem will be greatly appreciated!
>Thanks (ALOT) in advance,
>R. Kirk Waterhouse


A couple of responders suggested catching SIGCHLD.  Since this doesn't
really do what was wanted (fork() and forget), I'll point out that there
are indeed a couple of ways to do that (and without that FIFO mess) that
I have found to work.

What is happening is that UNIX expects that child processes, when they
die, to be wait()ed for by the parent.  Until then, they are
zombie/defunct.  UNIX needs to keep them until the parent gets around
to wait()ing (since it doesn't know _your_ parent process does not want to
eventually wait()), and they consume slots in the process table.  If,
however, the parent dies, they will be inherited by the init process (pid 1),
will be waited for, and thus dumped from the table.  The trick is,
then, for you to create processes with no parent.

The easiest method, which has drawbacks, is to do what you were trying
to do but reverse the role of parent and child process.  In other words,
have the _parent_ go do the "Channel x" stuff and the _child_ take
over the "My Process" which the parent had been doing.  Drawbacks?
One example would be trying to kill the "My Process."  Doing a "ps"
and then a "kill -TERM {pid}" where {pid} is what you got from ps
might kill instead a process now doing "Channel x" if a fork() occurred
in the meantime, for example.  This method may also leave a few defunct
processes around until the oldest of the bunch gets done.  Too messy.

Instead, I recommend the following, which I have used with much success:
     PARENT: fork() then wait() for death of CHILD, then go back to business
     CHILD:  fork() then exit() immediately
     GRANDCHILD:  run the program you really want to run.
Now the grandchild has no parent, and init will clean it up when
it (the grandchild) finishes.  Signal catching is not required, and "ps"
will show you what you expect for other purposes (except PPID will be 1
for the grandchild).  It costs an extra fork(), but leaves things "cleaner."

Good luck.

Stan.
--
X-Obligatory-.sig
    Stan Ryckman   sgr@alden.UUCP