C program on "waipid" system call usage [WIFSTOPPED and WIFCONTINUED]
"From the code in the above weblink,
minor changes are made to demonstrate WIFSTOPPED and WIFCONTINUED.
Also, refer the below link on how to test this code:
Note:
When you use SIGSTOP to a process it will
pause the process. It will not resume automatically unless you send a SIGCONT
signal to it. This is great because it allows you to pause a process without
terminating it.
Neelkanth_39$ cat
child_main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
/* the program should take 2 arguments */
if (((argc
>1) && (argc <= 3)))
{
printf("child: process name: %s\n", argv[0]);
printf("child: arguments %s %s\n", argv[1], argv[2]);
} else {
printf("child: enter only 2 random strings\n");
exit(1);
}
/* The child process would run indefinitely now */
printf("child:
Child process goes into infinite while loop\n");
printf("child: Issue (Kill -19 and Kill -18 in sequence) "
"to child process and see what happens\n");
while(1) {
sleep(10);
}
return 0;
}
Neelkanth_39$ cat parent_main_3.c
#include <errno.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
int main()
{
pid_t child_pid;
int status;
/* now create new process */
child_pid = fork();
int ret;
if (child_pid >= 0) /* fork succeeded */
{
if (child_pid == 0) /* fork()
returns 0 for the child process */
{
printf("parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
printf("parent:
start child process!\n");
printf("parent:
child PID = %d, parent pid = %d\n", getpid(), getppid());
char *cmd[] =
{"./child1", "neel", "rockstar", NULL};
return execvp(cmd[0],
cmd); // call child1 process
}
else /* parent process */
{
printf("parent:
*****************************************************\n");
printf("parent:
parent process!\n");
printf("parent:
parent PID = %d, child pid = %d\n", getpid(), child_pid);
/* wait for child to
exit, and store child's exit status */
printf("parent:
WAIT FOR THE CHILD PROCESS TO TERMINATE\n");
printf("parent:
*****************************************************\n");
/*
WUNTRACED also return if a child has stopped (but not traced
via
ptrace(2)). Status for traced children
which have
stopped is provided even if this option is
not specified.
WCONTINUED (since Linux 2.6.10)
also return if a stopped child has been
resumed by deliv‐
ery of SIGCONT.
*/
do {
ret =
waitpid(child_pid, &status, WUNTRACED | WCONTINUED);
if (ret
== -1) {
perror("waitpid");
exit(1);
}
/*
WIFSTOPPED(wstatus)
returns true if the child process was stopped by delivery of a
signal; this is possible only if the call was done using WUN‐
TRACED or when the child is being traced (see ptrace(2)).
kill -19 [SIGSTOP]
*/
if
(WIFSTOPPED(status)) {
printf("parent: stat value: %d Exit status: %d\n", status,
WSTOPSIG(status));
psignal(WSTOPSIG(status), "parent: child received STOP signal:
"
"Exit signal");
printf("parent: Child process to PAUSE at this point \n");
printf("parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
/*
WIFCONTINUED(wstatus)
(since Linux 2.6.10) returns true if the child process was
resumed by delivery of SIGCONT.
kill -18 [SIGCONT]
*/
if
(WIFCONTINUED(status)) {
printf("parent: stat value: %d Exit status: %d\n", status,
WIFCONTINUED(status));
printf("parent: child received SIGCONT signal\n");
printf("parent: Child process to RESUME from the point where it was
stopped earlier\n");
printf("parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
/*If child has exited on return from it's main function or exit(0): */
if
(WIFEXITED(status)) {
printf("parent: Child process has exited. exit code: %d\n",
WEXITSTATUS(status));
printf("parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
/*
if child has exited on receiving an exception signal
*
e.g. kill -11 (SIGSEGV),
-3 (SIQUIT),
-4 (SIGILL),
-5 (SIGTRAP),
-6 (SIGABRT),
-7 (SIGBUS),
-8 (SIGFPE),
*/
if
(WIFSIGNALED(status) && WCOREDUMP(status)) {
printf("parent: stat value: %d Exit status: %d\n", status,
WTERMSIG(status));
psignal(WTERMSIG(status), "parent: child received exception signal:
"
"Exit signal");
printf("parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
/*
if child has exited on receiving a termination signal
*
e.g. kill -15 (SIGTERM),
-2 (SIGINT),
-9 (SIGKILL),
-1 (SIGHUP),
-13 (SIGPIPE),
-14 (SIGALRM),
-16 (SIGSTKFLT),
*/
else if
(WIFSIGNALED(status)) {
printf("parent: stat value: %d Exit status: %d\n", status,
WTERMSIG(status));
psignal(WTERMSIG(status), "parent: Child received Termination
signal: "
"Exit signal");
printf("parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
}
}
/* Come out of
while loop, only when child process exits 'or'
* terminates on receiving
an exception signal.
* If child
process receives SIGSTOP (kill -19), parent can still wait
* till the child
actually terminates.
*/
while((!WIFEXITED(status)) && (!WIFSIGNALED(status)));
printf("parent:
*****************************************************\n");
printf("parent:
Parent exits now!\n\n");
printf("parent:
*****************************************************\n");
exit(0); /* parent
exits */
}
}
else /* failure */
{
perror("fork");
exit(0);
}
}
Output:
Terminal 1:
Neelkanth_39$ ./parent_main_3
parent:
*****************************************************
parent: parent process!
parent: parent PID =
32279, child pid = 32280
parent: WAIT FOR THE CHILD
PROCESS TO TERMINATE
parent:
*****************************************************
parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: start child process!
parent: child PID =
32280, parent pid = 32279
child: process name: ./child1
child: arguments neel rockstar
child: Child process goes into
infinite while loop
child: Issue (Kill -19
and Kill -18 in sequence) to child process and see what happens
parent: stat value: 4991 Exit status: 19
parent: child received STOP
signal: Exit signal: Stopped (signal)
parent: Child process to PAUSE
at this point
parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 65535 Exit
status: 1
parent: child received SIGCONT
signal
parent: Child process to RESUME
from the point where it was stopped earlier
parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 4991 Exit
status: 19
parent: child received STOP
signal: Exit signal: Stopped (signal)
parent: Child process to PAUSE
at this point
parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 65535 Exit
status: 1
parent: child received SIGCONT
signal
parent: Child process to RESUME
from the point where it was stopped earlier
parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 4991 Exit
status: 19
parent: child received STOP
signal: Exit signal: Stopped (signal)
parent: Child process to PAUSE
at this point
parent:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
parent: stat value: 65535 Exit
status: 1
parent: child received SIGCONT
signal
parent: Child process to RESUME
from the point where it was stopped earlier
parent: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Terminal 2:
Neelkanth_39$ kill -19 32270
Neelkanth_39$ pidof child1
32280
Neelkanth_39$ kill -19 32280
Neelkanth_39$ kill -18 32280
Neelkanth_39$ kill -19 32280
Neelkanth_39$ kill -18 32280
Neelkanth_39$ kill -19 32280
Neelkanth_39$ kill -18 32280