C program where parent waits for the child to terminate via termination signals and print the termination status

C program where parent waits for the child to terminate via termination signals and print the termination status


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("process name: %s\n", argv[0]);
        printf("arguments %s %s\n", argv[1], argv[2]);
    } else {
        printf("enter only 2 random strings\n");
        exit(1);
    }

    /* The child process would run indefinitely now */
    printf("Child process goes into infinite while loop\n");
    printf("Issue (Kill -15/ Kill -11/ any other termination signal) "
            "to child process and see what happens\n");

    while(1) {
       sleep(10);
    }

    return 0;
}

Neelkanth_39$ cat parent_main.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();

    if (child_pid >= 0) /* fork succeeded */
    {
        if (child_pid == 0) /* fork() returns 0 for the child process */
        {
            printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
            printf("start child process!\n");
            printf("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("*****************************************************\n");
            printf("parent process!\n");
            printf("parent PID =  %d, child pid = %d\n", getpid(), child_pid);

            /* wait for child to exit, and store child's exit status */
            printf("WAIT FOR THE CHILD PROCESS TO TERMINATE\n");
            printf("*****************************************************\n");
            wait(&status);

            /*If child has exited on return from it's main function or exit(0): */
            if (WIFEXITED(status)) {
                printf("Child process has exited. exit code: %d\n", WEXITSTATUS(status));
                printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
            }
             /* if child has exited on receiving a termination signal */
            else if (WIFSIGNALED(status)) {
                printf("stat value: %d Exit status: %d\n", status, WTERMSIG(status));
                psignal(WTERMSIG(status), "Exit signal");
            }

            printf("*****************************************************\n");
            printf("Parent exits now!\n\n");
            printf("*****************************************************\n");
            exit(0);  /* parent exits */
        }
    }
    else /* failure */
    {
        perror("fork");
        exit(0);
    }
}

Compilation steps:
gcc -o child1 child_main.c
gcc -o parent_main parent_main.c


Output:
Open 2 terminal windows. 

On Terminal 1 window, run ./parent_main
*****************************************************
parent process!
parent PID =  8458, child pid = 8459
WAIT FOR THE CHILD PROCESS TO TERMINATE
*****************************************************
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
start child process!
child PID =  8459, parent pid = 8458
process name: ./child1
arguments neel rockstar
Child process goes into infinite while loop
Issue (Kill -15/ Kill -11) to child process and see what happens

On 2nd terminal,
get pid of child1 process.
Neelkanth_39$ ps -elf | grep child
4 S root      1191  1155  0  80   0 - 41562 -      Oct14 ?        00:00:00 lightdm --session-child 16 19
0 S root      1238  1155  0  80   0 - 24159 -      Oct14 ?        00:00:00 lightdm --session-child 12 19
0 S labuser   8459  8458  0  80   0 -  1050 hrtime 07:11 pts/21   00:00:00 ./child1 neel rockstar
0 S labuser   8461  7727  0  80   0 -  3987 pipe_w 07:13 pts/19   00:00:00 grep --color=auto child

Issue Kill -11 to child1 process.
Neelkanth_39$ kill -11 8459

Again on Terminal 1 window, the parent process prints the exit status of the child process

stat value: 139 Exit status: 11
Exit signal: Segmentation fault
*****************************************************
Parent exits now!

*****************************************************


Output : [ when Kill -15 is issued to child1 process.]
Neelkanth_39$ ./parent_main
*****************************************************
parent process!
parent PID =  8463, child pid = 8464
WAIT FOR THE CHILD PROCESS TO TERMINATE
*****************************************************
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
start child process!
child PID =  8464, parent pid = 8463
process name: ./child1
arguments neel rockstar
Child process goes into infinite while loop
Issue (Kill -15/ Kill -11) to child process and see what happens

stat value: 15 Exit status: 15
Exit signal: Terminated
*****************************************************
Parent exits now!

*****************************************************

Neelkanth_39$ ps -elf | grep child
4 S root      1191  1155  0  80   0 - 41562 -      Oct14 ?        00:00:00 lightdm --session-child 16 19
0 S root      1238  1155  0  80   0 - 24159 -      Oct14 ?        00:00:00 lightdm --session-child 12 19
0 S labuser   8464  8463  0  80   0 -  1050 hrtime 07:16 pts/21   00:00:00 ./child1 neel rockstar
0 S labuser   8466  7727  0  80   0 -  3987 pipe_w 07:16 pts/19   00:00:00 grep --color=auto child
Neelkanth_39$ kill -15 8464



Output : [ when Kill -4 is issued to child1 process.]
Neelkanth_39$ ./parent_main
*****************************************************
parent process!
parent PID =  8470, child pid = 8471
WAIT FOR THE CHILD PROCESS TO TERMINATE
*****************************************************
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
start child process!
child PID =  8471, parent pid = 8470
process name: ./child1
arguments neel rockstar
Child process goes into infinite while loop
Issue (Kill -15/ Kill -11) to child process and see what happens

stat value: 132 Exit status: 4
Exit signal: Illegal instruction
*****************************************************
Parent exits now!


*****************************************************

Neelkanth_39$ ps -elf | grep child
4 S root      1191  1155  0  80   0 - 41562 -      Oct14 ?        00:00:00 lightdm --session-child 16 19
0 S root      1238  1155  0  80   0 - 24159 -      Oct14 ?        00:00:00 lightdm --session-child 12 19
0 S labuser   8471  8470  0  80   0 -  1050 hrtime 07:18 pts/21   00:00:00 ./child1 neel rockstar
0 S labuser   8475  7727  0  80   0 -  3987 pipe_w 07:18 pts/19   00:00:00 grep --color=auto child

Neelkanth_39$ kill -4 8471



###########################################################################
Enhanced Code: parent_main.c which also captures whether the signal received by the child is a termination signal or exception signal. 
###########################################################################
Neelkanth_39$ cat  parent_main.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();

    if (child_pid >= 0) /* fork succeeded */
    {
        if (child_pid == 0) /* fork() returns 0 for the child process */
        {
            printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
            printf("start child process!\n");
            printf("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("*****************************************************\n");
            printf("parent process!\n");
            printf("parent PID =  %d, child pid = %d\n", getpid(), child_pid);

            /* wait for child to exit, and store child's exit status */
            printf("WAIT FOR THE CHILD PROCESS TO TERMINATE\n");
            printf("*****************************************************\n");
            wait(&status);

             /*If child has exited on return from it's main function or exit(0): */
            if (WIFEXITED(status)) {
                printf("Child process has exited. exit code: %d\n", WEXITSTATUS(status));
                printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\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("stat value: %d Exit status: %d\n", status, WTERMSIG(status));
                psignal(WTERMSIG(status), "child received exception signal: "
                         "Exit signal");
                printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\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("stat value: %d Exit status: %d\n", status, WTERMSIG(status));
                psignal(WTERMSIG(status), "Child received Termination signal: "
                        "Exit signal");
                printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");         
            }

            printf("*****************************************************\n");
            printf("Parent exits now!\n\n");
            printf("*****************************************************\n");
            exit(0);  /* parent exits */
        }
    }
    else /* failure */
    {
        perror("fork");
        exit(0);
    }
}