在主线程调用pthread_exit后,它变成zombie.something错了?

时间:2012-06-21 02:35:43

标签: c linux pthreads proc

我想使用/proc/[pid]/task/枚举特定进程的线程。但在proc手册页中,它说:

  

在多线程进程中,如果主线程已经终止(通常通过调用pthread_exit(3)),则/ proc / [pid] / task目录的内容不可用。

然后我写了一些代码,

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

void* PrintHello(void* data){
  pthread_t tid = (pthread_t)data;
  int rc;

  rc = pthread_join(tid, NULL);
  if(rc){
    exit(1);
  } else{
    printf("Hello from new thread %d - got %d\n", pthread_self(), data);
    sleep(180);
    pthread_exit(NULL);
  }
}

int main(int argc, char* argv[]){
  int rc;
  pthread_t thread_id;
  thread_t tid;

  tid = pthread_self();
  printf("\nmain thread(%d) ", tid); 

  rc = pthread_create(&thread_id, NULL, PrintHello, (void*)tid);
  if(rc){
    printf("\n ERROR: return code from pthread_create is %d \n", rc);
    exit(1);
  }
  sleep(1);
  printf("\n Created new thread (%d) ... \n", thread_id);
  pthread_exit(NULL);
}
在主线程调用pthread_exit()之后,它转向僵尸。并且/ proc / [pid] / task目录仍然存在,但/ proc / [pid] / maps为空。

$ ./a.out & 
 main thread(164759360) 
 Created new thread (164755200) ... 
Hello from new thread 164755200 - got 164759360

$ ps auwx |  grep a.out
spyder    5408  0.0  0.0      0     0 pts/0    Zl+  10:27   0:00 [a.out] <defunct>
spyder    5412  0.0  0.0 109400   896 pts/1    S+   10:27   0:00 grep --color=auto a.out

$ ls /proc/5408/task/
5408  5409
$ cat /proc/5408/maps 
$ cat /proc/5408/status
Name:   a.out
State:  Z (zombie)
Tgid:   5408
Pid:    5408
....
$ cat /proc/5409/maps 
00400000-00401000 r-xp 00000000 fd:02 2752690                            /home/spyder/a.out
00600000-00601000 rw-p 00000000 fd:02 2752690                            /home/spyder/a.out
018cb000-018ec000 rw-p 00000000 00:00 0                                  [heap]
3dcf000000-3dcf020000 r-xp 00000000 fd:01 139203                         /usr/lib64/ld-2.15.so
3dcf21f000-3dcf220000 r--p 0001f000 fd:01 139203                         /usr/lib64/ld-2.15.so
....

有什么问题吗?

2 个答案:

答案 0 :(得分:1)

你已经倒退了。你在PrintHello函数上执行的函数正在加入main()线程,当它应该相反时:

main()主题/功能中,您应该致电:

(void)pthread_join(thread_id, NULL);

简而言之,pthread_join()意味着“在我做任何其他事情之前,等待'和'确定''thread_id'的线程完成”。你的代码基本上是这样说的:

  1. 启动main()程序逻辑
  2. 创建一个线程,做一些printf()和sleep()的东西,然后退出整个程序
  3. 与此同时,你创建了一个在main()去世之前不会做任何事情的线程
  4. 当main()死掉时,它会隐藏所有内容,因此PrintHello()线程无法正常关闭,因为join()调用可能会失败
  5. 你可能打算这样做(请注意额外的评论):

    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    void* PrintHello(void* data){
      pthread_t tid = (pthread_t)data;
    
      //pthread_join(tid, NULL);  //WRONG
      printf("Hello from new thread %d - I was launched by thread number: %d\n", pthread_self(), data);
      sleep(180); //Sleep for 3 minutes, for no reason really
      pthread_exit(NULL); //All done in this thread
    }
    
    int main(int argc, char* argv[]){
      int rc;
      pthread_t thread_id;
      long int tid;
    
      tid = pthread_self();
    
      rc = pthread_create(&thread_id, NULL, PrintHello, (void*)tid);
      if(rc) {
        printf("\n ERROR: return code from pthread_create is %d; Thread probably didn't get created\n", rc);
        exit(1);
      }
      sleep(1); //Sleep, for no reason
      printf("\n Created new thread (%d) ... Now let's wait for it to finish\n", thread_id);
      pthread_join(thread_id, NULL); //Wait for the child thread to finish it's work
      return 0; //All done!
    }
    

    如果我的假设是正确的,请说明是这种情况,我可以做一些进一步的更正。祝你好运!

答案 1 :(得分:0)

根据我对pthreads库如何工作的理解,我认为僵尸线程的原因是通常将与主线程连接会丢弃其资源,因为主线程会返回一个状态(通过返回主函数)可能并且在某些情况下预期由父进程使用(即,通过使用等待),在线程组完全退出之前,该线程不能被完全销毁(即,整个过程已退出)。如果以某种方式允许将pthread_exit调用的值返回给父进程,那么父进程将认为该子进程已经退出,这是不正确的,因为 PrintHello 函数仍然在运行。