[comp.unix.questions] Avoiding <exiting> processes on Ultrix

jw@pan.UUCP (Jamie Watson) (04/08/89)

I know this sounds trivial, but I have searched the Ultrix (and 4.3)
manuals everywhere I can think of, and I can't find the answer.

Is there any way under Ultrix (2.0 or later) to write a C program
such that any child processes created by that program will exit,
without hanging in an <exiting> status until the parent does a wait()
for the child?  Under SysV this is done with signal(SIGCLD, SIG_IGN);
I have tried that under Ultrix, to no avail.

jw

gwyn@smoke.BRL.MIL (Doug Gwyn ) (04/09/89)

In article <520@pan.UUCP> jw@pan.UUCP (Jamie Watson) writes:
>Is there any way under Ultrix (2.0 or later) to write a C program
>such that any child processes created by that program will exit,
>without hanging in an <exiting> status until the parent does a wait()
>for the child?  Under SysV this is done with signal(SIGCLD, SIG_IGN);
>I have tried that under Ultrix, to no avail.

Ugh!  NEVER use the SIGCLD kludge!

To create a child that will not become a long-lived zombie:

	if ( fork() == 0 )
		if ( fork() == 0 )
			exec( whatever );
		else
			_exit( 0 );

Since the grandchild has no parent, whenever it terminates it will
be reaped by the "init" special process.

peter@ficc.uu.net (Peter da Silva) (04/09/89)

The following should help. The returned PID is bogus, but you didn't care
for it anyway, right? I can't return the real pid easily, since exit eats
8 bits of the return value.

dfork()    /* Fork and detach, so you can run stuff from a daemon */
{
    int pid, status;

    switch(pid==fork()) {    /* Create a sacrificial child */
        case -1: /* Failure */

            return -1; /* return error code */

        default: /* In parent */

            while(wait(&status) != pid)    /* find child */
                continue;

            if(status)
                return -1;/* error, assume fork failed */
            else
                return pid;/* fork succeeded -- PID BOGUS */

        case 0:    /* In sacrificial child */

            switch(fork()) {
                case -1:     /* fork failed, tell boss */
                    exit 1;
                case 0:     /* return in child */
                    return 0;
                default:     /* fork succeeds, tell boss */
                    exit 0;  /* And sacrifice child to daemon */
                }
        }
}
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

bernsten@phoenix.Princeton.EDU (Dan Bernstein) (04/12/89)

In article <520@pan.UUCP> jw@pan.UUCP (Jamie Watson) writes:
> Is there any way under Ultrix (2.0 or later) to write a C program
> such that any child processes created by that program will exit,
> without hanging in an <exiting> status until the parent does a wait()
> for the child?  Under SysV this is done with signal(SIGCLD, SIG_IGN);
> I have tried that under Ultrix, to no avail.

I'm surprised nobody's mentioned setting up a SIGCLD/SIGCHLD handler
that does a wait().

  sigchld() { wait(0); }

  signal(SIGCHLD,sigchld);

This is faster (on some machines, much much faster) than an extra
fork(). It is certainly more general than ignoring the signal, and
it's the basis for the shell job control (with a more intelligent
sigchld()).

---Dan Bernstein, bernsten@phoenix.princeton.edu

chris@mimsy.UUCP (Chris Torek) (04/12/89)

In article <7693@phoenix.Princeton.EDU> bernsten@phoenix.Princeton.EDU
(Dan Bernstein) writes:
>I'm surprised nobody's mentioned setting up a SIGCLD/SIGCHLD handler
>that does a wait().

(I did, in a mailed reply.)

>  sigchld() { wait(0); }
>
>  signal(SIGCHLD,sigchld);

This is not correct.  SIGCHLD signals are not queued (in either BSD
or [SIGCLD] SysV), nor are they `regenerated' as they are in SysV.
The child handler must use wait3 with the WNOHANG option:

	while ((w = wait3(&status, WNOHANG, (struct rusage *)0)) >= 0)
		/* void */;

Otherwise, if several child processes exit in quick succession,
one or more may be missed.

(Also, that should be `wait((int *)0)' or `wait((union wait *)0)',
although `union wait' probably should not have been invented.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris