-4

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で機能する必要がありますか?そうでない場合、それは未定義または未指定ですか?

4

1 に答える 1

4

POSIXに関する限り、いくつかの問題があります。

  • ドキュメントにpthread_exit()よると、「最後のスレッドが終了した後、プロセスは終了ステータス0で終了します。動作は、スレッドの終了時に引数がゼロのexit()を呼び出した実装のようです。」
  • ドキュメントにexit()は、「atexit()の呼び出しによって登録された関数が戻らない場合、残りの登録された関数は呼び出されず、残りのexit()処理は完了しません。exit()がさらに呼び出された場合一度以上、動作は未定義です」。

つまり、厳密に言えば、pthread_exit()最後のスレッドに対してが呼び出された場合、その動作はexit()複数回呼び出されたかのようになります。つまり、未定義の動作です。

とはいえ、発生するはずの最悪の事態は、最後のスレッドが終了したときにアプリケーションがクラッシュまたはデッドロックすることだと思います。プロセスはとにかく終了しているため、アプリケーションの性質と、テストでリスクがどれだけ低いかを示すレベルによっては、リスクが許容される場合があります。

どのスレッドが最後に終了するかを知ることができれば、atexit()を呼び出す代わりに、コールバックでセマフォ、条件変数、またはミューテックスをブロックできると思いますpthread_exit()。呼び出しpthread_exit()(または戻る)しようとしているときに、最後のスレッドにそのブロックを解放させます。

于 2012-08-14T15:02:42.443 に答える