使用atexit调用pthread_exit

时间:2012-08-14 14:01:09

标签: c++ pthreads posix language-lawyer

atexit来电pthread_exit是否合法?没有它,main()返回时,所有线程都被终止。 (简单的解决方案是修改main()以调用pthread_exit()本身,但在这个最小示例来自的实例中,这是不可能的。)

#include <unistd.h>
#include <cstdlib>
#include <iostream>
#include <pthread.h>

void *foo(void *data) {
  for (int i = 0; i < 10; ++i) {
    std::cout << i << "\n";
    sleep(1);
  }
  return NULL;
}

void foo_init() {
  std::atexit([](){
    pthread_exit(NULL);
  });
}

int main() {
  foo_init();
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  pthread_t thr;
  pthread_create(&thr, &attr, foo, NULL);
}

pthread_exit州的联合帮助页:

  

线程终止不释放任何应用程序可见的进程资源,包括但不限于互斥锁和文件描述符,也不执行任何进程级别的清理操作,包括但不限于调用任何atexit()例程可能存在。

这似乎排除了疯狂递归破坏事物的风险。

它还声明:

  

如果从作为对pthread_exit()的隐式或显式调用的结果而调用的取消清除处理程序或析构函数调用,则pthread_exit()的行为是未定义的。

这表示有些地方未定义来调用pthread_exit,但是(除非主要花费10秒钟返回,这假设在“真实”案例中是不可能的)不是适用。

这个例子“对我有用”但需要POSIX工作吗?如果不是未定义或未指定?

1 个答案:

答案 0 :(得分:4)

就POSIX而言,存在一些问题:

  • docs for pthread_exit()说:“进程在最后一个线程终止后以退出状态0退出。行为就好像实现在线程终止时调用带有零参数的exit()” / LI>
  • docs for exit()表示,“如果通过调用atexit()注册的函数无法返回,则不应调用剩余的注册函数,并且不应完成exit()处理的其余部分。 exit()被多次调用,行为未定义“。

严格地说,当为最后一个线程调用pthread_exit()时,行为就好像exit()被多次调用一样,也就是说它是未定义的行为。

那就是说,我认为应该发生的最坏情况是当最后一个线程退出时应用程序将崩溃或死锁。由于该过程无论如何都会退出,风险可能是可接受的,具体取决于您的应用程序的性质以及您的测试表明风险可能有多低。

如果您可以安排知道最后一个退出的线程,我认为您可以阻止atexit()回调中的信号量,条件变量或互斥,而不是调用pthread_exit()。将最后一个线程释放时,阻止它将要调用pthread_exit()(或返回)。