[comp.unix.ultrix] Firing up a process and not wait

jet@lavaca.uh.edu (J. Eric Townsend) (12/20/89)

Maybe there's an obvious answer to this that I didn't hit while
RTFM'ing.  While in process foo, I want to crank up process bar
and have it run independently of foo.  system("bar &") doesn't do
the trick, as a wait() is still called for the parent shell of bar (it
seems that's what happening, at least).

Any suggestions?  No flames, please, this is my first foray into doing
sockets/networking/daemon code...
work: Department of Mathematics
      University of Houston   (713) 749 2120
      Houston, Tx 77204-3476  jet@karazm.math.uh.edu
home: jet@flatline.UUCP

klee@chico.pa.dec.com (Ken Lee) (12/20/89)

In article <1989Dec19.191032.21857@lavaca.uh.edu>, jet@lavaca.uh.edu (J.
Eric Townsend) writes:
> Maybe there's an obvious answer to this that I didn't hit while
> RTFM'ing.  While in process foo, I want to crank up process bar
> and have it run independently of foo. 

The standard way of doing this is to fork (or vfork) and execl (or
execv).  Any good UNIX programming book should have example code.

Ken Lee
DEC Western Software Laboratory, Palo Alto, Calif.
Internet: klee@decwrl.dec.com
uucp: uunet!decwrl!klee

bph@buengc.BU.EDU (Blair P. Houghton) (12/21/89)

In article <1989Dec19.191032.21857@lavaca.uh.edu> jet@lavaca.uh.edu (J. Eric Townsend) writes:
>
>Maybe there's an obvious answer to this that I didn't hit while
>RTFM'ing.

It's not obvious.  It's a bit of idiomatic wizardry that
you would have found in any Unix-programming-in-C book,
though.

>While in process foo, I want to crank up process bar
>and have it run independently of foo.  system("bar &") doesn't do
>the trick, as a wait() is still called for the parent shell of bar (it
>seems that's what happening, at least).

	/* fork a nother process. */

	if ( !fork() )
	    exec("bar",...);

Read the manual pages for fork(), and use the correct
exec-function (there are a slew of them that will work
under ultrix:  execl, execv, execle, execlp, execvp, exect,
and execve) to get this to work.

The basic thing is that fork() makes an exact, running copy
of the process you are running.  It returns to the original
process the pid of the new process, and "returns" to the
new process a 0.  So, now there are two programs running
separately on the system, with only their pid's, ppid's,
and the return value from this fork() to distinguish them.
They are totally independent, unless you use the returned
pid of the child explicitly in a wait-call (there's a pile
of those, too: wait, wait3, and waitpid).

The trick is to take the new process and immediately change
it, using one of the exec family, which clears out the
running process and fires up the process in the file named
in the argument to the exec call.

You'd think something as common as this (and it's in about
every program ever written that gets put into a unix
release) would become a system call of its own.  I guess the
number and variety of the exec's keeps that from happening.

Last hint:  execv("bar",(char *)NULL) is your best bet, but
look over the others to make sure you're using the features
of these functions correctly.

Absolute final hint:  There is no function that is
named exec(), and I have not the slightest idea why...

				--Blair
				  "Down and dirty systems programming."

barmar@Think.COM (12/21/89)

In article <2308@bacchus.dec.com> klee@decwrl.dec.com writes:
>In article <1989Dec19.191032.21857@lavaca.uh.edu>, jet@lavaca.uh.edu (J.
>Eric Townsend) writes:
>> While in process foo, I want to crank up process bar
>> and have it run independently of foo. 
>The standard way of doing this is to fork (or vfork) and execl (or
>execv).

Don't you still have to wait() for it to prevent the child process from
becoming a zombie when it exits?

I think some versions of Unix check whether the parent has set up a handler
for the SIGCHILD signal when deciding whether to zombify the child.
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

kline@tuna.cso.uiuc.edu (Charley Kline) (12/22/89)

> Don't you still have to wait() for it to prevent the child process from
> becoming a zombie when it exits?

The sleazy way around this is to

    ...
    if (!fork()) {
	if (!fork()) {
	    execl("/usr/bin/foo", "foo", "bar", 0);
	    _exit(1);  /* in case exec fails */
	    }
	exit(0);       /* exit child */
	}
    wait(0);
    ...

This double fork creates a child, which creates a grandchild, which
execs the desired program. The child exits without waiting on the
grandchild, thus the init process inherits the grandchild and will
wait() for it.  The parent then waits for the child, and since the
child exits very quickly, the parent can continue in short order. Of
course this isolates the parent from the grandchild, so the parent
can't get any exit status information from the grandchild process.


Of course the more proper way to do this is to create a SIGCHLD handler
which, when fired, does a wait3() with the WNOHANG option in a loop
until -1 is returned, then resets the signal and returns. This way the
parent waits for the children as it's supposed to (and can get status
information from the child).

Yours in Section 2,
_____
Charley Kline, University of Illinois Computing Services
c-kline@uiuc.edu
uunet!uiucuxc!kline

"Oh Bliss! Oh Rapture!"  "Oh Rapture! Oh Bliss!"