POSIX スレッドの挙動について

2013/Dec/9


先日、とあるプログラムで /proc/net/arp が読めない、という話が出た。正確には、あるときから突然 open(2) が失敗する、ということだった。

シェルから cat /proc/net/arp で情報はとれるし、open(2) して close(2) するだけのプログラムを作って試してみたが、これも問題ないという。

そのプログラムは処理を一発やっておしまい、というものではなく、ネットワークの監視プログラムの機能の一部として取り込まれ、トラブルなどでも無い限り止めたりはしない、ということだった。

前任者がいなくなって長らく放置状態ではあったが、プログラム自体は機能していたし、特に問題視されることもなく、そのプログラムも含めて機器まるごと更新をしたところ、エラーが出るようになった、という、いかにもありがちなケースだった。

ソースがあるだけよかった、だのなんなのと、この先なんやかんやあるのだけれど、そこはつまらないので全部飛ばそう。

プログラムは、対象ごとにスレッドが作られること、作成されたスレッドが pthread_detach(3) して、スレッドはそれぞれ多少のデータの受け渡しはあったが、基本的に独立して動作することが想定されていた。

肝心の不具合は、起動直後から起きるのではなく、一定時間が経ってから起き始めていた。

やってることは独立しているのに、初期化順序や依存関係がこじれていて、最初は何をやりたいのかさっぱりだったのが、そこかしこにログを埋め込んで整理していたところ、機器自体の故障は、ネットワーク等々の監視スレッドを一通り動かし始めた後に、main() が受け持つ構造になっていた。

機器本体の故障監視部分は障害が発生したと判断すると、障害報告を送信してエラーを止めようとしていたのだろうけど、止まるはずがないコードだった。

最後の最後に pthread_exit(3) を呼び出していて、そのスレッドだけが死んでいた。

そりゃ、止まらねーよ。

今回のケースは機器が変更されて動作しなくなるようなコードなのに、修正することなくプログラムをそのまま稼働させようとしていたから起きたので、その該当部分を修正すれば動作するようになるのだが、いまいち納得感がない。

そもそも、なんで、main() が pthread_exit(3) で終わったら、生きてるやつが /proc/net/arp を open(2) しようとする ENOENT になるのかがさっぱり分からない。

再現ソースは次の場所に置いておいた。Gist: cvsync / main-pthread_exit.c

main() が役目を終えて pthread_exit(3) すると、どんな問題が起きうるのか、そういや知らないなぁ。どっかにまとまってないかなぁ。


戻る