Bug 14689

Summary: waitpid doesn't harvest child process when program run under cron
Product: Base System Reporter: wpk <wpk>
Component: i386Assignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   

Description wpk 1999-11-03 19:40:00 UTC
waitpid(pid, &status, 0) doesn't harvest a child process when
used in a program compiled with -D_REENTRANT, linked with libc_r.a
and run from cron.

The program forks. the parent waits for the child using waitpid(pid, &status, 0).
the parent times out the waitpid with a sigalrm. the child sleeps and
then exits. the waitpid call times out. The problem occurs only when the program
is run from cron, compiled with -D_REENTRANT and linked with libc_r.a

How-To-Repeat: contact me for code to reproduce the problem
Comment 1 Sheldon Hearn 1999-11-04 14:14:07 UTC
On Wed, 03 Nov 1999 11:38:18 PST, wpk@isc.org wrote:

> The program forks.
> the parent waits for the child using waitpid(pid, &status, 0).
> the parent times out the waitpid with a sigalrm.
	     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> the child sleeps and then exits.
> the waitpid call times out.
      ^^^^^^^^^^^^^^^^^^^^^^

Impossible.  Perhaps you should send some sample code?

Ciao,
Sheldon.
Comment 2 Sheldon Hearn 1999-11-04 16:24:11 UTC
On Thu, 04 Nov 1999 08:38:43 CST, William King wrote:

> find attached x.tar containing x.c and makefile. make x and
> run it under cron. then try running it by hand.

Ah.

The parent arranges for delivery of a SIGALRM in 60 seconds.
The program forks.
The parent waits on the child pid with waitpid().
The child sleeps 10 seconds, then exits.
The parent returns from waitpid() on receipt of SIGARLM.

When the program is not run from cron, the parent returns from waitpid()
when the child exits as expected.

Ciao,
Sheldon.
Comment 3 jmb 1999-11-16 13:23:58 UTC
program run under cron


Bill, 
	Thanks for the code snippet.  I am going to add the code and
the results of running it to the bug tracking system.

jmb

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
run from an xterm:

baby:[215] ./x
child 26962, deadpid 26962, errno 0, T_int 0
deadpid == child

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
run from cron

child 26951, deadpid -1, errno 4, T_int 14
terminating child
child 26951, deadpid 26951, errno 3, T_int 0
deadpid == child

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Example Code:

#include    <ctype.h>
#include    <errno.h>
#include    <limits.h>
#include    <stdarg.h>
#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <sys/wait.h>
#include    <signal.h>
#include    <time.h>
#include    <unistd.h>
#include    <pthread.h>


#define T_TIMEOUT   60

static int  T_timeout;
static int  T_int;

static void t_sighandler();

static void
t_sighandler(int sig) {
    T_int = sig;
}

int
main(int argc, char **argv)
{

    pid_t           child;
    pid_t           deadpid;
    int         status;
    struct sigaction    sa;

    T_timeout = T_TIMEOUT;

    /* setup signals */

    sa.sa_flags = 0;
    sigfillset(&sa.sa_mask);
    sa.sa_handler = t_sighandler;
    (void) sigaction(SIGALRM, &sa, NULL);
    (void) sigaction(SIGINT,  &sa, NULL);

    setbuf(stdout, NULL);

    child = fork();
    if (child == 0) {
        sleep(10);
        exit(0);
    }
    else if (child > 0) {

        T_int = 0;
        sa.sa_handler = t_sighandler;
        (void) sigaction(SIGALRM, &sa, NULL);
        alarm(T_timeout);

        deadpid = (pid_t) -1;
        while (deadpid != child) {
            deadpid = waitpid(child, &status, 0);
	printf("child %d, deadpid %d, errno %d, T_int %d\n", 
		child, deadpid, errno, T_int);
            if (deadpid == child) {
                printf("deadpid == child\n");
                if (WIFSIGNALED(status)) {
                    if (WTERMSIG(status) == SIGTERM)
                        printf("the test case timed out\n");
                    else
                        printf("the test case caused exception %d\n",
				WTERMSIG(status));
                }
            }
            else if ((deadpid == -1) && (errno == EINTR) && T_int) {
                printf("terminating child\n");
                kill(child, SIGTERM);
                T_int = 0;
            }
            else if ((deadpid == -1) &&
                 ((errno == ECHILD) || (errno == ESRCH))) {
                printf("no such process\n");
                break;
            }
        }

        sa.sa_handler = SIG_IGN;
        (void) sigaction(SIGALRM, &sa, NULL);
        alarm(0);
    }
    else {
        printf("fork failed, errno == %d\n", errno);
    }

    return(0);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comment 4 Mike Barcroft freebsd_committer freebsd_triage 2001-07-21 03:29:27 UTC
State Changed
From-To: open->feedback


Does this problem still occur in newer versions of FreeBSD, 
such as 4.3-RELEASE?
Comment 5 Mike Barcroft freebsd_committer freebsd_triage 2001-07-21 03:35:19 UTC
State Changed
From-To: feedback->closed


E-mail sent to originator bounces.