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") ;
}
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.