Thread: execv and defunct process

  1. #1
    Registered User
    Join Date
    Dec 2004
    Posts
    41

    execv and defunct process

    Hello All,

    I have made a small program to execute an external program using execv. First I make some sanity check's like if the file exist then I execute the program (by root) doing an setuid to the user that requested the action. The execv is done after forking the process so my master process can still run.

    The problem that I see is that even after the program/script ends, the instance created doesn't die, it remains at my process list as an defunct process consuming memory and cpu.

    Here is the code:

    Code:
            switch ((pid = fork()))
            {
                    case -1:
                            /* Fork() has failed */
                            perror ("fork");
                            return 0;
                            break;
                    case 0:
                            /* This is processed by the child */
                            //execv ("/tmp/echo1.sh", my_args);
                            setuid(userid);
                            execv (prog, argument);
                            printf("Failed to run prog [%s] for userid [%s]\n",prog,userid);
                            exit(EXIT_FAILURE);
                            return 0;
                            break;
                    default:
                            /* This is processed by the parent */
                            return 0;
                            break;
            }

    The process list:

    Code:
    26617 ?        S      0:00 executeit
    26618 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26634 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26646 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26658 ?        Z      0:00  \_ [run_trigger_bil <defunct>]
    26659 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26682 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26694 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26706 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26718 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26730 ?        Z      0:00  \_ [run_trigger_bil <defunct>]
    26731 ?        Z      0:00  \_ [executeit <defunct>]
    26732 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26755 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26767 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26783 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26795 ?        Z      0:00  \_ [run_read_to_pro <defunct>]
    26810 ?        Z      0:00  \_ [run_trigger_bil <defunct>]
    31258 ?        S      0:00  \_ /bin/sh /home/groo/run_read_to_profilo.sh 
    31268 ?        S      0:00  |   \_ /usr/bin/php /home/groo/read_to_profilo.php
    31269 ?        Z      0:00  \_ [run_trigger_bil <defunct>]
    31270 ?        Z      0:00  \_ [executeit <defunct>]

    top:

    Code:
      PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME COMMAND
     8308 groous     8   0     0    0     0 Z     0.5  0.0   0:00 run_read_to_pro <defunct>
     8296 groous     8   0     0    0     0 Z     0.9  0.0   0:00 run_read_to_pro <defunct>
     8284 groous     8   0     0    0     0 Z     0.5  0.0   0:00 run_read_to_pro <defunct>
     8261 groous     8   0     0    0     0 Z     0.5  0.0   0:00 run_trigger_bil <defunct>
     8262 groous     8   0     0    0     0 Z     0.3  0.0   0:00 run_read_to_pro <defunct>
     8249 groous     8   0     0    0     0 Z     0.3  0.0   0:00 run_read_to_pro <defunct>

    I'm using Linux Red Hat 8.0.


    Any help ?

    Thanks a lot,

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Code:
                    default:
                            /* This is processed by the parent */
                            return 0;
                            break;
    The problem is you don't wait for the child to complete. A process which ends goes into a 'Z' (zombie) state until the parent process calls wait() to get it's exit status.

    There are a series of wait() and waitpid() calls which have a great deal of flexibility.

    Eg.
    waitpid( (pid_t)-1, WNOHANG );
    allows you to quickly check if any child has exited, and in doing so, finally release the child process from being a zombie.

    Since I imagine you don't want your parent to hang around in the default of your switch, then put this call in your main loop.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3

  4. #4
    Registered User
    Join Date
    Dec 2004
    Posts
    41
    Hey Salem and orbitz, thanks a lot for the solution !

    I've made some coding and now it works just fine !!!


    Thanks again,

  5. #5
    Registered User
    Join Date
    Dec 2004
    Posts
    41
    Hello Again,

    I've found a problem today with this implemantation. My program dies allways after 108 seconds. I've done this:

    At main():
    Code:
        struct sigaction act;
        /* Assign sig_chld as our SIGCHLD handler */
        act.sa_handler = sig_chld;
        /* We don't want to block any other signals */
        sigemptyset(&act.sa_mask);
        /* We're only interested in children that have terminated */
        act.sa_flags = SA_NOCLDSTOP;
    Inside for(; at main():
    Code:
        /* sleep */
        usleep(100000); //100ms
    
        /* Make these values effective. */
        if (sigaction(SIGCHLD, &act, NULL) < 0) {
            fprintf(stderr, "sigaction failed\n");
            return 0;
        }
    function:
    Code:
    /*
     * The signal handler function -- only gets called when a SIGCHLD
     * is received, ie when a child terminates
     */
    void sig_chld(int signo)
    {
        int status, child_val;
    
        /* Wait for any child without blocking */
        if (waitpid(-1, &status, WNOHANG) < 0)
        {
            /*
             * calling standard I/O functions like fprintf() in a 
             * signal handler is not recommended.
             */
            //fprintf(stderr, "waitpid failed\n");  //only for DEBUG
            return;
        }
    
        /*
         * We now have the info in 'status' and can manipulate it using
         * the macros in wait.h.
         */
        if (WIFEXITED(status))                /* did child exit normally? */
        {
            child_val = WEXITSTATUS(status); /* get child's exit status */
            printf("child's exited normally with status %d\n", child_val);
        }
    }
    I've done some debuging but didn't found anything logical !

    Any help ?

    Thanks,

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Some of what you're doing is not allowed inside signal handlers.
    A signal handler is a restricted environment, you have to be pretty careful about what you do in there. Unless you know a specific function is 'safe to be called inside a signal handler', then assume that it can't.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. No call to execv
    By protocol78 in forum C Programming
    Replies: 4
    Last Post: 05-08-2007, 11:43 AM