I created parent process and child process. And then from the child process, I created 3 more grand child processes.
From child process, SIGTERM is sent to the grand child processes and wait the grand child process terminated using waitpid().
waitpid() returns unknown error for a grand child process out of 3 grand child processes. waitpid() does not return unknown errors for the other 2 grand child processes.
I compiled the code and run it. Then, I got the message like below.
$ ./a.out
shm_create : shmid = 0
main_process
child process pid = 1953
in grand_chile_process2 : pid = 1955
in grand_child_process2-1
g_child_id->pid[0] = 0
g_child_id->pid[1] = 1955
g_child_id->pid[2] = 0
in process2-2
in grand_child_process1 : pid = 1954
in process1-1
g_child_id->pid[0] = 1954
g_child_id->pid[1] = 1955
g_child_id->pid[2] = 0
in process1-2
in grand_child_process3 : pid = 1956
in process3-1
g_child_id->pid[0] = 1954
g_child_id->pid[1] = 1955
g_child_id->pid[2] = 1956
in process3-2
And if I check running processes, I saw 5 processes like below.
# ps -eLf | grep a.out
user1 1952 1684 1952 0 1 13:51 pts/2 00:00:00 ./a.out
user1 1953 1952 1953 0 1 13:51 pts/2 00:00:00 ./a.out
user1 1954 1953 1954 0 1 13:51 pts/2 00:00:00 ./a.out
user1 1955 1953 1955 0 1 13:51 pts/2 00:00:00 ./a.out
user1 1956 1954 1956 0 1 13:51 pts/2 00:00:00 ./a.out
root 1958 1885 1958 0 1 13:51 pts/4 00:00:00 grep --color=auto a.out
And if I enter 'a', then I see the error message like below.
a
Terminating...: pid = 1956
error : waitpid (No child processes)
And the process list became as shown below.
# ps -eLf | grep a.out
user1 1952 1684 1952 0 1 13:51 pts/2 00:00:00 ./a.out
user1 1953 1952 1953 0 1 13:51 pts/2 00:00:00 [a.out] <defunct>
user1 1954 1 1954 0 1 13:51 pts/2 00:00:00 ./a.out
user1 1955 1 1955 0 1 13:51 pts/2 00:00:00 ./a.out
user1 1956 1954 1956 0 1 13:51 pts/2 00:00:00 [a.out] <defunct>
root 1960 1885 1960 0 1 13:51 pts/4 00:00:00 grep --color=auto a.out
Here, as shown in the source code below, I sent SIGTERM to grand_child_process3() the first and grand_child_process2() and then grand_child_process1() between line 218~246.
And I made a change to send SIGTERM in the order of grand_child_process1(), grand_child_process2() and grand_child_process3().
Then, again I can see the output like below.
$ ./a.out
shm_create : shmid = 0
main_process
child process pid = 1985
in grand_chile_process2 : pid = 1987
in grand_child_process2-1
g_child_id->pid[0] = 0
g_child_id->pid[1] = 1987
g_child_id->pid[2] = 0
in process2-2
in grand_child_process1 : pid = 1986
in process1-1
g_child_id->pid[0] = 1986
g_child_id->pid[1] = 1987
g_child_id->pid[2] = 0
in process1-2
in grand_child_process3 : pid = 1988
in process3-1
g_child_id->pid[0] = 1986
g_child_id->pid[1] = 1987
g_child_id->pid[2] = 1988
in process3-2
And the process list shows like below.
# ps -eLf | grep a.out
user1 1984 1684 1984 0 1 14:03 pts/2 00:00:00 ./a.out
user1 1985 1984 1985 0 1 14:03 pts/2 00:00:00 ./a.out
user1 1986 1985 1986 0 1 14:03 pts/2 00:00:00 ./a.out
user1 1987 1985 1987 0 1 14:03 pts/2 00:00:00 ./a.out
user1 1988 1986 1988 0 1 14:03 pts/2 00:00:00 ./a.out
root 1990 1885 1990 0 1 14:03 pts/4 00:00:00 grep --color=auto a.out
Then, again pressed 'a' and the output becomes like below.
a
Terminating...: pid = 1986
pid = 1986
child process[1986] killed by signal 15 (Terminated)
Terminating...: pid = 1987
pid = 1987
child process[1987] killed by signal 15 (Terminated)
Terminating...: pid = 1988
error : waitpid (No child processes)
Then, process list became like this.
# ps -eLf | grep a.out
user1 1984 1684 1984 0 1 14:03 pts/2 00:00:00 ./a.out
user1 1985 1984 1985 0 1 14:03 pts/2 00:00:00 [a.out] <defunct>
root 1992 1885 1992 0 1 14:05 pts/4 00:00:00 grep --color=auto a.out
My question is why grand_child_process3() is not terminated properly.
If you see anything I'm doing wrong, please let me know. Here is the full source code I'm using.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <error.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/wait.h>
#define KEY_NUM 1234
pid_t g_child1, g_child2, g_child3;
int shmid;
struct _process_id {
pid_t pid[3];
};
typedef struct _process_id G_CHILD_ID_t;
int shared_memory_create()
{
void *shared_memory;
shmid = shmget((key_t)KEY_NUM, sizeof(G_CHILD_ID_t), IPC_CREAT|0666);
if (shmid == -1)
{
printf("shmget failed\n");
exit(0);
}
printf("shm_create : shmid = %d\n", shmid);
shared_memory = shmat(shmid, NULL, 0);
if (shared_memory == (void *)-1)
{
printf("shmat failed\n");
exit(0);
}
memset(shared_memory, 0x0, sizeof(G_CHILD_ID_t));
if(shmdt(shared_memory) == -1)
{
printf("shmdt failed\n");
exit(0);
}
return 0;
}
int grand_child_process1(void)
{
G_CHILD_ID_t *g_child_id;
void *shared_memory;
int i = 0;
g_child1 = getpid();
printf("in grand_child_process1 : pid = %d\n", g_child1);
shared_memory = shmat(shmid, NULL, 0);
if (shared_memory == (void *)-1)
{
printf("shmat failed\n");
exit(0);
}
g_child_id = (G_CHILD_ID_t *)shared_memory;
g_child_id->pid[0] = g_child1;
printf("in process1-1\n");
for (i = 0 ; i < 3 ; i++)
printf("g_child_id->pid[%d] = %d\n", i, g_child_id->pid[i]);
if(shmdt(shared_memory) == -1)
{
printf("shmdt failed\n");
exit(0);
}
printf("in process1-2\n");
while(1)
{
sleep(1);
}
}
int grand_child_process2(void)
{
G_CHILD_ID_t *g_child_id;
void *shared_memory;
int i = 0;
g_child2 = getpid();
printf("in grand_chile_process2 : pid = %d\n", g_child2);
shared_memory = shmat(shmid, NULL, 0);
if (shared_memory == (void *)-1)
{
printf("shmat failed\n");
exit(0);
}
g_child_id = (G_CHILD_ID_t *)shared_memory;
g_child_id->pid[1] = g_child2;
printf("in grand_child_process2-1\n");
for (i = 0 ; i < 3 ; i++)
printf("g_child_id->pid[%d] = %d\n", i, g_child_id->pid[i]);
if(shmdt(shared_memory) == -1)
{
printf("shmdt failed\n");
exit(0);
}
printf("in process2-2\n");
while(1)
{
sleep(1);
}
}
int grand_child_process3(void)
{
G_CHILD_ID_t *g_child_id;
void *shared_memory;
int i = 0;
g_child3 = getpid();
printf("in grand_child_process3 : pid = %d\n", g_child3);
shared_memory = shmat(shmid, NULL, 0);
if (shared_memory == (void *)-1)
{
printf("shmat failed\n");
exit(0);
}
g_child_id = (G_CHILD_ID_t *)shared_memory;
g_child_id->pid[2] = g_child3;
printf("in process3-1\n");
for (i = 0 ; i < 3 ; i++)
printf("g_child_id->pid[%d] = %d\n", i, g_child_id->pid[i]);
if(shmdt(shared_memory) == -1)
{
printf("shmdt failed\n");
exit(0);
}
printf("in process3-2\n");
while(1)
{
sleep(1);
}
}
void printWaitStatus(pid_t pid, int status)
{
printf("pid = %d\n", pid);
if (WIFEXITED(status))
{
printf("child process[%d] exited, status = %d\n", pid, WEXITSTATUS(status));
}
else if (WIFSIGNALED(status))
{
printf("child process[%d] killed by signal %d (%s)\n", pid, WTERMSIG(status), strsignal(WTERMSIG(status)));
}
else if (WIFSTOPPED(status))
{
printf("child process[%d] stopped by signal %d (%s)\n", pid, WSTOPSIG(status), strsignal(WSTOPSIG(status)));
}
}
int child_process(void)
{
G_CHILD_ID_t *g_child_id;
void *shared_memory;
int wstatus;
int err;
pid_t p1, p2;
char ch;
printf("child process pid = %d\n", getpid());
p1 = fork();
p2 = fork();
if (p1 == 0 && p2 > 0)
{
grand_child_process1();
}
else if (p1 > 0 && p2 == 0)
{
grand_child_process2();
}
else if (p1 == 0 && p2 == 0)
{
grand_child_process3();
}
shared_memory = shmat(shmid, NULL, 0);
if (shared_memory == (void *)-1)
{
printf("shmat failed\n");
exit(0);
}
g_child_id = (G_CHILD_ID_t *)shared_memory;
while (1)
{
ch = (char)getchar();
if (ch == 'a')
{
printf("Terminating...: pid = %d\n", g_child_id->pid[2]);
kill(g_child_id->pid[2], SIGTERM);
err = waitpid(g_child_id->pid[2], &wstatus, WUNTRACED | WCONTINUED);
if (err == -1)
{
printf("error : waitpid (%s)\n", strerror(errno));
exit(EXIT_FAILURE);
}
printWaitStatus(g_child_id->pid[2], wstatus);
printf("Terminating...: pid = %d\n", g_child_id->pid[1]);
kill(g_child_id->pid[1], SIGTERM);
err = waitpid(g_child_id->pid[1], &wstatus, WUNTRACED | WCONTINUED);
if (err == -1)
{
printf("error : waitpid (%s)\n", strerror(errno));
exit(EXIT_FAILURE);
}
printWaitStatus(g_child_id->pid[1], wstatus);
printf("Terminating...: pid = %d\n", g_child_id->pid[0]);
kill(g_child_id->pid[0], SIGTERM);
err = waitpid(g_child_id->pid[0], &wstatus, WUNTRACED | WCONTINUED);
if (err == -1)
{
printf("error : waitpid (%s)\n", strerror(errno));
exit(EXIT_FAILURE);
}
printWaitStatus(g_child_id->pid[0], wstatus);
if(shmdt(shared_memory) == -1)
{
printf("shmdt failed\n");
exit(0);
}
}
else
sleep(1);
}
return 0;
}
int main_process(void)
{
printf("main_process \n");
while (1)
{
sleep(1);
}
}
int main(void)
{
pid_t pid;
shared_memory_create();
pid = fork();
if (pid == 0)
{
child_process();
}
else
{
main_process();
}
}