kzk さんに教えてもらったネタ

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6336770

Javaは新しいプロセス作るときに、ファイルディスクリプタを全部閉じようとするけども、実装がバグっているのでデッドロックが起きる可能性があるそうだ。

てきとうに見つけたクロスリファレンスサイトから引用すると
http://www.jiema.org/xref/openjdk/jdk7/jdk/src/solaris/native/java/lang/UNIXProcess_md.c#293

fork-and-exec処理の時のディスクリプタ全クローズ処理で、よりにもよってopendir()。ここでmalloc()が発生。あぼーん。

なんで、UNIX系OSってcloseall()システムコールがないんだろうね。困ったもんだ


追記: Linux限定の話でいうと /proc/{pid}/statusのFDSizeフィールドがmax fdを表しているので、3からFDSizeまでcloseしていけば、OKなんじゃないかという気がしてきた。誰か検証プリーズ

追記2: ついでにRubyの実装をちらりと見たけど、NOFILEまでしかクローズしていないから最大ファイルディスクリプタが動的なシステムだとリークしているっぽい。今度、akrさんあたりに真相を聞いてみよう。

追記3: glibc malloc はpthread_atfork()を使って、fork前後でmutexを取っているので、forkとexecの間でmalloc()呼んでも平気。これはtcmallocのような外部mallocを使った場合のみに問題になりそう

追記4: いくつかのページで sysconf(_SC_OPEN_MAX)を薦めているところがあったけど、これ、Linuxではうまくいかない。getrlimit()で現在のlimitを取っているだけなので、ファイルを開いた後で最大値を下げられたら、ちゃんとハンドリングできない。まあ、普通の人はそんな事しない。という指摘は正しいと思います

追記5: forkとexecの間はasync signal safeしかダメって話は以前にも書いたので、そっちも見てね
http://mkosaki.blog46.fc2.com/blog-entry-886.html

追記6: kzkさんに指摘されて気づいたけど、これが記念すべき1000エントリ目かー。妙に感慨深いな

追記7: kzkさんの関連エントリも参照のこと。
http://kzk9.net/blog/2009/09/deadlock_on_process_builder.html