8

Why does Linux consider a process whose main thread has terminated to be a zombie process, and is there any way to avoid this?

In the code below I:

  1. Create a process with one main thread
  2. Create a new detached thread
  3. pthread_exit the main thread
  4. pthread_exit the detached thread

Before #3, ps(1) shows my process as a normal process. After #3, however, ps(1) shows my process as a zombie (e.g., 2491 pts/0 00:00:00 thread-app <defunct>) even though it still has running threads.

Is it possible to quit the main thread but avoid going into a zombie state?

Code:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>

void *thread_function(void *args)
{
printf("The is new thread! Sleep 20 seconds...\n");
sleep(20);
printf("Exit from thread\n");
pthread_exit(0);
}

int main(int argc, char **argv)
{
pthread_t thrd;
pthread_attr_t attr;
int res = 0;
res = pthread_attr_init(&attr);
res = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
res = pthread_create(&thrd, &attr, thread_function, NULL);
res = pthread_attr_destroy(&attr);
printf("Main thread. Sleep 5 seconds\n");
sleep(5);
printf("Exit from main process\n");
pthread_exit(0);
}

# ./thread-app
pilcrow
  • 56,591
  • 13
  • 94
  • 135
likern
  • 3,744
  • 5
  • 36
  • 47
  • 1
    maybe you want `ptherad_join()`? – Sourav Ghosh Nov 18 '14 at 14:05
  • I want new thread, which will live longer than original main thread. And that main thread is destroyed correctly, without beeing zombie. – likern Nov 18 '14 at 14:18
  • so you want to detach the thread from the mean thread using http://linux.die.net/man/3/pthread_detach :) – MimiEAM Nov 18 '14 at 14:19
  • What's the difference between pthread_detach() and pthread_attr_setdetachstate()? I think they as the same. But pthread_detach() will transfer "joined" thread to "detached", after pthread_create(), but pthread_attr_setdetachstate() will create with "detached" state right away in pthread_create() call. – likern Nov 18 '14 at 14:22
  • 2
    @likern, I edited your post heavily but I think it better reflects your question. Roll back the edit if you disagree. – pilcrow Nov 18 '14 at 14:24
  • 1
    I think the reason is that main and new thread has shared memory and data which owned by main thread can be used by new thread - thus can't be freed even after main thread finishes his job. For this reason main thread is set to zombie state. – likern Nov 18 '14 at 14:39
  • 1
    @likern, According to posix standard, you are correct. I think Linux is using the parent thread to track all of the pthread information. pthread_exit knows and keeps the process around, not calling wait on it. In linux it may be impossible to do what you ask. My general coding policy is to keep the main thread alive until all of the children are gone, to avoid an undefined state, so I hadn't seen this until you brought it up. – DAhrens Nov 18 '14 at 14:41
  • So, given @DAhrens' inference, the next question is ... why does it matter? What logic do you have that is upset by the process being listed as a "zombie", even though a `wait()` call will eventually succeed? – pilcrow Nov 18 '14 at 14:57
  • @pilcrow, the question more about how it is working and why, not how to do something. It's dispute between me and my friend. I told that threads as special processes in Linux ("Linux Kernel Development" book directly says that), but I don't see behaviour similar to processes - new threads can't survive exit() call, and if main thread calls pthread_exit - is still waiting child threads, but in zombie state. – likern Nov 18 '14 at 15:10

2 Answers2

5

This is a known issue. A fix proposed a while ago by Kaz wasn't accepted by Ulrich Drepper. His comment on this was:

I haven't looked at the patch nor tried it.

If the patch changes the behavior that the main thread, after calling
sys_exit, still react to signals sent to this thread or to the process
as a whole, then the patch is wrong. The userlevel context of the
thread is not usable anymore. It will have run all kinds of
destructors. The current behavior is AFAIK that the main thread won't
react to any signal anymore. That is absolutely required.

Read the mail chain for more discussion on this here:

http://lkml.iu.edu/hypermail/linux/kernel/0902.0/00153.html

P.P
  • 117,907
  • 20
  • 175
  • 238
3

The operating-system thinks your process is a zombie because the main thread, which was started by the operating-system, returned (i.e., exited). If you don't want this behavior, then don't have the main thread exit.

Steve Emmerson
  • 7,702
  • 5
  • 33
  • 59
  • 1
    I'd add that this is a nominal zombie (a "nombie" ?). The termination of the main thread via `pthread_exit` when other threads are running does _not_ generate a SIGCHLD, nor does it interrupt any `wait`-like calls in the parent. The process is "defunct" more-or-less only from the perspective of _ps(1)_. – pilcrow Nov 18 '14 at 17:31
  • 1
    Well, all threads are started by operating system in that sense. `pthread_exit()`, by definition, should exit only the current thread, just like when it's called from any other thread. So, it's perfectly reasonable to expect main thread to behave in the way as any other thread in the process. But of course, it doesn't. – P.P Nov 18 '14 at 19:17
  • Obviously, the main thread *isn't* like any other thread: it *doesn't* have to be created by `pthread_create()` and the operating-system is allowed to treat its termination as special. – Steve Emmerson Nov 18 '14 at 21:05