Reputation: 89
I'm using waitpid to get status code returned by the child when it changes state. I'm using:
if (WIFEXITED(code)){
if (WEXITSTATUS(code)==0){
//worked correctly
}
else{
//failed, throw error
}
}
else{
..
}
In the bottom part, I want to check for whether the child changed state without terminating and wait for it to terminate using a loop. How can I do so?
Upvotes: 1
Views: 2184
Reputation: 44043
Assuming you don't ptrace
the child process, you have to wait for it with the WUNTRACED
and WCONTINUED
flags:
waitpid(pid, &code, WUNTRACED | WCONTINUED);
If you do ptrace
it, WUNTRACED
is unnecessary, but since ptrace
is a different kettle of fish altogether, I'll not go into it in detail.
Then, you can check what happened like so:
if (WIFEXITED(code)) {
// process ended normally with exit status WEXITSTATUS(code)
} else if(WIFSIGNALLED(code)) {
// process was terminated by signal WTERMSIG(code)
} else if(WIFSTOPPED(code)) {
// child was stopped by signal WSTOPSIG(code)
} else if(WIFCONTINUED(code)) {
// child was continued
}
To get a feeling for the way this works, you can play around with this piece of code:
#include <stddef.h>
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid;
pid = fork();
if(pid == -1) {
fputs("fork failed\n", stderr);
} else if(pid == 0) {
int i;
for(i = 0; i < 100; ++i) {
usleep(1000000);
puts("child");
}
} else {
int status;
printf("%d\n", pid);
do {
waitpid(pid, &status, WUNTRACED | WCONTINUED);
printf("exited: %d status: %d\n"
"signalled: %d signal: %d\n"
"stopped: %d signal: %d\n"
"continued: %d\n",
WIFEXITED(status),
WEXITSTATUS(status),
WIFSIGNALED(status),
WTERMSIG(status),
WIFSTOPPED(status),
WSTOPSIG(status),
WIFCONTINUED(status));
} while(!WIFEXITED(status) && !WIFSIGNALED(status));
}
return 0;
}
This will fork, the parent process will print the process ID of the child process, and when you send the child process signals, the parent will print the status properties it gets from waitpid
(not all of them will make sense, naturally; if the process is stopped, WTERMSIG
does not return anything meaningful). Here's my example output from a session in which I sent the child process SIGSTOP
, SIGCONT
, and SIGTERM
:
38167
child
child
child
child
exited: 0 status: 19
signalled: 0 signal: 127
stopped: 1 signal: 19
continued: 0
exited: 0 status: 255
signalled: 0 signal: 127
stopped: 0 signal: 255
continued: 1
child
child
child
exited: 0 status: 0
signalled: 1 signal: 15
stopped: 0 signal: 0
continued: 0
Upvotes: 1