I observed that when terminating a process with D-state thread(s), the process would keep in zombie state, instead of being reclaimed by init (pid-1). Here comes the steps to reproduce this behavior.
Test Environment
2 x Red Hat Enterprise Linux 6.7
|
-- NFS Server
|
-- NFS Client (Run below code in this server)
Example Code
[root@rhel674 tmp]# cat zstate2.c
/****
This example code will create 3 threads,
one thread will keep writing data to a file in NFS mount point,
the other two threads will keep sleeping, doing nothing.
****/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include <pthread.h>
void *task1();
void *task2();
void *task3();
int main()
{
pthread_t thread1,thread2,thread3;
const char *message1 = "Thread 1";
const char *message2 = "Thread 2";
const char *message3 = "Thread 3";
int iret1, iret2, iret3;
iret1 = pthread_create ( &thread1, NULL, task1, NULL);
if(iret1)
{
fprintf(stderr, "Error - pthread_create() return code: %d\n", iret1);
return 1;
}
iret2 = pthread_create ( &thread2, NULL, task2, NULL);
if(iret2)
{
fprintf(stderr, "Error - pthread_create() return code: %d\n", iret2);
return 2;
}
iret3 = pthread_create ( &thread3, NULL, task3, NULL);
if(iret3)
{
fprintf(stderr, "Error - pthread_create() return code: %d\n", iret3);
return 3;
}
printf("pthread_create() for thread 1 returns: %d\n",iret1);
printf("pthread_create() for thread 2 returns: %d\n",iret2);
printf("pthread_create() for thread 3 returns: %d\n",iret3);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
pthread_join( thread3, NULL);
return 0;
}
/* This task read a NFS file. Could be in D state */
void *task1()
{
FILE *pFile;
pFile=fopen("/mnt/nfs/testfile", "r+");
while(1){
fprintf (pFile, "test");
}
}
/* Sleeping */
void *task2()
{
while(1){
sleep(1);
}
}
/* Sleeping */
void *task3()
{
while(1){
sleep(1);
}
}
/****
This example code will create 3 threads,
one thread will keep writing data to a file in NFS mount point,
the other two threads will keep sleeping, doing nothing.
****/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include <pthread.h>
void *task1();
void *task2();
void *task3();
int main()
{
pthread_t thread1,thread2,thread3;
const char *message1 = "Thread 1";
const char *message2 = "Thread 2";
const char *message3 = "Thread 3";
int iret1, iret2, iret3;
iret1 = pthread_create ( &thread1, NULL, task1, NULL);
if(iret1)
{
fprintf(stderr, "Error - pthread_create() return code: %d\n", iret1);
return 1;
}
iret2 = pthread_create ( &thread2, NULL, task2, NULL);
if(iret2)
{
fprintf(stderr, "Error - pthread_create() return code: %d\n", iret2);
return 2;
}
iret3 = pthread_create ( &thread3, NULL, task3, NULL);
if(iret3)
{
fprintf(stderr, "Error - pthread_create() return code: %d\n", iret3);
return 3;
}
printf("pthread_create() for thread 1 returns: %d\n",iret1);
printf("pthread_create() for thread 2 returns: %d\n",iret2);
printf("pthread_create() for thread 3 returns: %d\n",iret3);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
pthread_join( thread3, NULL);
return 0;
}
/* This task read a NFS file. Could be in D state */
void *task1()
{
FILE *pFile;
pFile=fopen("/mnt/nfs/testfile", "r+");
while(1){
fprintf (pFile, "test");
}
}
/* Sleeping */
void *task2()
{
while(1){
sleep(1);
}
}
/* Sleeping */
void *task3()
{
while(1){
sleep(1);
}
}
Compile this code with below command:
# gcc -Wall -pthread -o zstate2 zstate2.c
Test Steps
1. In NFS Client, run the above program:
# mount -t nfs <nfs-server>:<nfs-share> /mnt/nfs
# /tmp/zstate2
# /tmp/zstate2
2. After a while, poweroff (shut it down forcefully ) NFS Server.
Then we will see a zstate2 thread keep in D-state:
[root@HA6-0 ~]# ll /proc/3801/task/ <<<---- 3801 is the pid of zstate2
total 0
dr-xr-xr-x. 6 root root 0 Apr 12 18:38 3801
dr-xr-xr-x. 6 root root 0 Apr 12 18:38 3802
dr-xr-xr-x. 6 root root 0 Apr 12 18:38 3803
dr-xr-xr-x. 6 root root 0 Apr 12 18:38 3804
[root@HA6-0 ~]# cat /proc/380{1,2,3,4}/status | grep -i state
Name: zstate2
State: S (sleeping)
Name: zstate2
State: D (disk sleep)
Name: zstate2
State: S (sleeping)
Name: zstate2
State: S (sleeping)
total 0
dr-xr-xr-x. 6 root root 0 Apr 12 18:38 3801
dr-xr-xr-x. 6 root root 0 Apr 12 18:38 3802
dr-xr-xr-x. 6 root root 0 Apr 12 18:38 3803
dr-xr-xr-x. 6 root root 0 Apr 12 18:38 3804
[root@HA6-0 ~]# cat /proc/380{1,2,3,4}/status | grep -i state
Name: zstate2
State: S (sleeping)
Name: zstate2
State: D (disk sleep)
Name: zstate2
State: S (sleeping)
Name: zstate2
State: S (sleeping)
3. Send SIGTERM signal to this process:
[root@HA6-0 ~]# kill 3801
[root@HA6-0 ~]# cat /proc/380{1,2,3,4}/status | grep -i state
cat: /proc/3803/status: No such file or directory
cat: /proc/3804/status: No such file or directory
Name: zstate2
State: Z (zombie)
Name: zstate2
State: D (disk sleep)
[root@HA6-0 ~]# cat /proc/380{1,2,3,4}/status | grep -i state
cat: /proc/3803/status: No such file or directory
cat: /proc/3804/status: No such file or directory
Name: zstate2
State: Z (zombie)
Name: zstate2
State: D (disk sleep)
And we will see the one thread keeps in D state, and the leader thread (process) keeps in Z state.