C program on "waipid" system call usage [WIFSTOPPED and WIFCONTINUED]

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