waitpid with execl used in child returns -1 with ECHILD?

14,180

If you wait with WNOHANG, then you won't get any useful status unless your child has already died — and it may not even have got going yet (it could still be waiting for the executable to be loaded from disk when the parent executes the waitpid()).

If you want to know that the child has finished, don't use WNOHANG — use 0 for the third argument unless you want to know about untraced or continued processes. This will wait until the process identified by Checksum_pid exits, or the system loses track of it by some mysterious means (which I've never seen happen).


This code produces Exit Code: 0 as the output:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void)
{
    pid_t Checksum_pid = fork();

    if (Checksum_pid < 0)
        printf("Fork Failed\n");
    else if (Checksum_pid == 0)
    {
        execl("/bin/sleep", "/bin/sleep", "2", NULL);
        exit(EXIT_FAILURE);
    }
    else
    {
        int childStatus;
        pid_t returnValue = waitpid(Checksum_pid, &childStatus, 0);

        if (returnValue > 0)
        {
            if (WIFEXITED(childStatus))
                printf("Exit Code: %d\n", WEXITSTATUS(childStatus));
            else
                printf("Exit Status: 0x%.4X\n", childStatus);
        }
        else if (returnValue == 0)
            printf("Child process still running\n");
        else
        {
            if (errno == ECHILD)
                printf(" Error ECHILD!!\n");
            else if (errno == EINTR)
                printf(" Error EINTR!!\n");
            else
                printf("Error EINVAL!!\n");
        }
    }

    return 0;
}

It is very similar to your code; I've merely moved the check for fork() failing to the top. I'd still prefer to get rid of the 'bushy trees' of if statements, but it isn't critical. What happens when you run this code? What do you have to change to get the ECHILD error (can you change it so that you get the ECHILD error)?

When you've managed to get code based off this to reproduce the problem, we can work out why you get that behaviour.

Tested on Mac OS X 10.9.2 Mavericks with GCC 4.8.2, and also Ubuntu 13.10 with GCC 4.8.1 (I needed to add -D_XOPEN_SOURCE=700 to get it to compile with my stringent compilation flags; Mac OS X managed without that), but I don't expect to get different results elsewhere.

Share:
14,180
kapilddit
Author by

kapilddit

Miles to go before I sleep. Working with Bosch India - RBEI.

Updated on June 28, 2022

Comments

  • kapilddit
    kapilddit almost 2 years

    When do I need to use waitpid if I am using execl in a child process which may take time to finish?

    When I use waitpid in the parent, it tells me that the child is running as the return value from waitpid is 0. However, if I call waitpid after some time in another function, it returns -1 with errno set to ECHILD. When should I use waitpid if I am not sure whether the child has completed or not?

    //pid_t Checksum_pid = fork();
    Checksum_pid = fork();
    
    if (Checksum_pid == 0)
    {
        execl(path, name, argument as needed, ,NULL);
        exit(EXIT_SUCCESS);     
    }
    else if (Checksum_pid > 0)
    { 
        pid_t returnValue = waitpid(Checksum_pid, &childStatus, WNOHANG);
    
        if ( returnValue > 0)
        {
            if (WIFEXITED(childStatus))
            {
                printf("Exit Code: _ WEXITSTATUS(childStatus)") ;               
            }
        }
        else if ( returnValue == 0)
        {
            //Send positive response with routine status running (0x03)
            printf("Child process still running") ; 
        }
        else
        {
            if ( errno == ECHILD )
            {
                 printf(" Error ECHILD!!") ;
            } 
            else if ( errno == EINTR )
            {
                // other real errors handled here.
                printf(" Error EINTR!!") ;
            }
            else
            {
                printf("Error EINVAL!!") ;
            }       
        }
    }
    else
    {   
        /* Fork failed. */
        printf("Fork Failed") ;
    }
    
    • Jonathan Leffler
      Jonathan Leffler about 10 years
      The exit(EXIT_SUCCESS); after the execl() is the wrong indicator; if execl() returns, it failed, so you should really exit with exit(EXIT_FAILURE); to let the parent process know you failed.
    • kapilddit
      kapilddit about 10 years
      When I try to use printf in child process above execl and below execl. I was not able to get any prints... I don't know why. I think above execl I should get the print. Am I write? If execl success then how can exit from child process to terminate it? If I am using waitpid not in parent process (somewhere in other function after some execution) then is it valid to use waitpid with same childpid as first argument which I got in parent process?
  • kapilddit
    kapilddit about 10 years
    Then What I need to use? What is the meaning If I pass 0 as optional 3rd argument instead of WNOHANG?
  • kapilddit
    kapilddit about 10 years
    What are the arguments I need to use in waitpid ? I tried with WCONTINUED but No success. Shall I use WUNTRACED?
  • kapilddit
    kapilddit about 10 years
    I tried with 0 as third argument to waitpid but still its giving ERROR : ECHILD!! If does exit(0) in child process mean it will be terminated with exit code 0? Here In my case execl is successful.
  • kapilddit
    kapilddit about 10 years
    I have two set of function 1) start : in which I want to use execl in child process which will execute script file & generate the output file. 2) parse_display_res: In this function I will use the generated output file (from start function) to extract the result. So It is necessary to have output file before extracting the data.
  • Jonathan Leffler
    Jonathan Leffler about 10 years
    You could fall back on the older int corpse = wait(&status); which simply waits for a child to die and reports on it, or returns -1 if there are no children left. Otherwise, post a complete SSCCE (Short, Self-Contained, Correct Example) or MCVE ([Minimal, Complete, Verifiable Example](http:stackoverflow.com/help/mcve)) of the problem code (set up to run sleep 5 as the child process, for example).
  • kapilddit
    kapilddit about 10 years
    I used int return_value = wait(&child_status); Still Error is ECHILD with return value -1 from wait. When I removed execl (with waitpid) from the child process it is showing me "child process still running". How can I know child finished successfully? I don't know why child is terminating abnormally.
  • Jonathan Leffler
    Jonathan Leffler about 10 years
    Please study how to create a MCVE How to create a Minimal, Complete, and Verifiable Example? or SSCCE (Short, Self-Contained, Correct Example), two names for the same basic idea. In the code above, what is g_area? What is the value of ScriptPath and ScriptName? What value of Area did you pass? Why do none of your messages end with a newline (they won't appear reliably until they do). Why are there so many blank lines in the code? Why don't you print the WEXITSTATUS value, instead of including the macro name in the output?
  • kapilddit
    kapilddit about 10 years
    @ Jonathan Leffler I copied the same code which you suggested over here. I tested the same thing on ubuntu, its working as expected as you describe but when I am trying the same code on my target its giving me an error: waitpid returns -1 with ECHILD. do you have any clue how it could happen?
  • Jonathan Leffler
    Jonathan Leffler about 10 years
    Succinctly, no — I have no idea how you're getting ECHILD. Which platform are you working on? Are you saying that the program above produces the ECHILD result? Or did you try to work my code into your program and it produces the ECHILD result? You'll need to post your MCVE (How to create a Minimal, Complete, and Verifiable Example?) or SSCCE (Short, Self-Contained, Correct Example) along with the information to identify your platform and compiler.