Thread: Checking for child process errors?

  1. #1
    Registered User
    Join Date
    Apr 2010
    Posts
    34

    Checking for child process errors?

    If i was to create a child process that executes a program, and then send some garbage to the child program through a pipe, resulting in an error, how would i detect an error like this in the parent process?

    Would i check to see if the program exited or check an error flag/function like stderror?

    This would be developed under unix, if that helps.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    That depends on what you wrote your child program to do in case of error. If you print to stderr, well, that's too bad since I don't believe you're going to get that into a pipe. You can print a message to the pipe, but your parent has to be ready to deal with that input. If it aborts/exits, then the parent program will get information if you've called wait. Your processes have a different errno variable IIRC, but you can return that.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You can do either (or both).
    - the parent reads a pipe attached to the stderr of the child process.
    - the parent uses wait() to obtain the exit status, then uses various 'W' macros (see man page) to analyse the status.
    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.

  4. #4
    Registered User
    Join Date
    Apr 2010
    Posts
    34
    I don't think I would want to use wait(), as if I sent correct information to the child program, I don't want the parent to stall at wait(), if the child program will not exit, until further input is sent.

    How would I make the child print to stderr when an error occurred?

    After the execlp() in child, would I just say fprint(stderr,xx,xxxx), because the child should never get to that statement after the exec, unless an error occurs?

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    I think you should post an actual example of what you're trying to do.
    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.

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Blasz View Post
    I don't think I would want to use wait(), as if I sent correct information to the child program, I don't want the parent to stall at wait(), if the child program will not exit, until further input is sent.
    Whether you want to or not, you must call wait(). If you do not, your program is incorrect. You don't have to call it RIGHT AWAY... But you have to call it.

    If you detect error by reading the child's output, how do you expect to not stall there as well? You try to read from a pipe and... it blocks until the child writes something.

    If you want asynchronous notification when the child terminates, install a signal handler for the SIGCHLD signal. When this signal triggers, you can call waitpid() on the child's PID, it will NOT block, and you can get the return status.

    Alternatively, you can poll the child with waitpid() and the WNOHANG flag -- if the child hasn't terminated yet, it doesn't block.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by brewbuck View Post
    Whether you want to or not, you must call wait(). If you do not, your program is incorrect.
    Why?

    Quote Originally Posted by Blasz View Post
    How would I make the child print to stderr when an error occurred?
    fprintf(stderr). But I think what Salem means here is that if I do this at the command line:

    [root/etc] asdf
    bash: asdf: command not found


    That error message is printed to stderr by the shell. This will happen via exec calls too, you might be able to catch it with read() on the child's stderr (but I doubt it, since this is not the exec'd process's stderr). What would work is to use popen() to read the programs stdout, and append 2>&1 to redirect it's stderr to stdout, which popen supplies. I've done that a lot, it works.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by MK27 View Post
    Why?
    Because a terminated child is a zombie until the parent calls wait(). It's the same thing as never free()'ing what you malloc(), or never fclose()'ing what you fopen(). Yes, the system will clean up your mess for you when you terminate, but it's not right, and it CERTAINLY doesn't fly in a program where you launch children repeatedly.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by brewbuck View Post
    Because a terminated child is a zombie until the parent calls wait(). It's the same thing as never free()'ing what you malloc(), or never fclose()'ing what you fopen().
    Fair enough -- altho it is not quite the same thing since zombie resources have already, in fact, been freed by the kernel. They just remain in the process list.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by MK27 View Post
    [root/etc] asdf
    bash: asdf: command not found


    That error message is printed to stderr by the shell. This will happen via exec calls too, you might be able to catch it with read() on the child's stderr (but I doubt it, since this is not the exec'd process's stderr). What would work is to use popen() to read the programs stdout, and append 2>&1 to redirect it's stderr to stdout, which popen supplies. I've done that a lot, it works.
    The stderr of child can be redirected using the dup2() call, the same way stdin and stdout is.
    This way the parent will be able to catch the error message string and decide what to do.
    All this means is that the array of file descriptors now has three elements instead of two.

  11. #11
    Registered User
    Join Date
    Apr 2010
    Posts
    34
    f you want asynchronous notification when the child terminates, install a signal handler for the SIGCHLD signal. When this signal triggers, you can call waitpid() on the child's PID, it will NOT block, and you can get the return status.
    Can you suggest a good site that tells you how to setup a sighandler?

    The man page didn't really help.

  12. #12
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by Blasz View Post
    Can you suggest a good site that tells you how to setup a sighandler?

    The man page didn't really help.
    Why is it that everyone complains about Google but no one seems to use it? First hit on grepping for SIGCHILD example:
    Code:
    #include <sys/types.h>  /* include this before any other sys headers */
    #include <sys/wait.h>   /* header for waitpid() and various macros */
    #include <signal.h>     /* header for signal functions */
    #include <stdio.h>      /* header for fprintf() */
    #include <unistd.h>     /* header for fork() */
    
    void sig_chld(int);     /* prototype for our SIGCHLD handler */
    
    int main() 
    {
        struct sigaction act;
        pid_t pid;
    
        /* Assign sig_chld as our SIGCHLD handler */
        act.sa_handler = sig_chld;
    
        /* We don't want to block any other signals in this example */
        sigemptyset(&act.sa_mask);
    
        /*
         * We're only interested in children that have terminated, not ones
         * which have been stopped (eg user pressing control-Z at terminal)
         */
        act.sa_flags = SA_NOCLDSTOP;
    
        /*
         * Make these values effective. If we were writing a real 
         * application, we would probably save the old value instead of 
         * passing NULL.
         */
        if (sigaction(SIGCHLD, &act, NULL) < 0) 
        {
            fprintf(stderr, "sigaction failed\n");
            return 1;
        }
    
        /* Fork */
        switch (pid = fork())
        {
        case -1:
            fprintf(stderr, "fork failed\n");
            return 1;
    
        case 0:                         /* child -- finish straight away */
            _exit(7);                   /* exit status = 7 */
    
        default:                        /* parent */
            sleep(10);                  /* give child time to finish */
        }
    
        return 0;
    }
    
    /*
     * 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, but probably OK 
             * in toy programs like this one.
             */
            fprintf(stderr, "waitpid failed\n");
            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);
        }
    }
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why isn't the execlp() function doing anything?
    By jsrig88 in forum C Programming
    Replies: 5
    Last Post: 10-12-2009, 10:09 AM
  2. sequenceing or queueing multiple process
    By sv_joshi_pune in forum Windows Programming
    Replies: 1
    Last Post: 08-14-2009, 09:43 AM
  3. Ten Errors
    By AverageSoftware in forum Contests Board
    Replies: 0
    Last Post: 07-20-2007, 10:50 AM
  4. process ring
    By gregulator in forum C++ Programming
    Replies: 0
    Last Post: 02-28-2005, 08:21 PM
  5. Checking for errors on output streams
    By Heraclitus in forum C Programming
    Replies: 1
    Last Post: 03-27-2003, 03:47 PM