- 2009-09-15 (Tue) 10:20
- Uncategorized

id:nobu-qが踏んだバグ。Twitterにて、kosaki先生に凄く色々アドバイスを頂いた。革命の日々の1000エントリ目のネタゲット!
やりたいこととしては、C++のマルチスレッドプログラムから、HDFS(Hadoop Distributed File system)にアクセスしたい。そのために、libhdfsを使用している。
HadoopはJavaで記述されているために、libhdfsは内部でJavaのコードを呼び出している。このJavaのクライアントライブラリが、ユーザー名などを取得するために”whoami”コマンドを呼び出しており、fork(2)を行う。その際にデッドロックが起きていた。
コードの階層は次のようになる。mallocの実装には、tcmalloc 1.2を使用していた。
C++ Server
C++ libhdfs
Java HDFSClient
Java ProcessBuilder
JavaVM
JavaVM C Layer
tcmalloc
デッドロックが起こっている箇所は、tcmallocの内部だった。よくよく調べてみると、Java VMがfork(2)とexec(2)の間に、親プロセスが開いている全てのファイルディスクリプタを閉じるために/proc/self/fdをopendir(3)している。ここでmallocが呼ばれている。
- UNIXProcess_md.c
- bug 6336770
最初は、tmallocがpthread_atforkでmutexをきちんと処理していないので、こちらが悪いと思っていた。が、kosaki先生によるとそもそもfork(2)
とexec(2)の間ではasync-signal safeな関数しか呼んではいけないらしい(これはPOSIXの仕様???)。mallocの実装は関係が無い。
解決策としては、まずアプリを動かすためだけなら、Hadoop側を改変してProcessBuilderを使わないようにすれば良い。
JVMの方を直すには、一番理想的にはFD_CLOSEEXECを使う方法だけど、これは変更範囲が大きそうだし漏れが有りそう。
なので、async-signal safeな関数だけを用いて、現在開いている全てのファイルディスクリプタ番号を取得する方法が必要となる。で、どうするかを今調べているところ。SolarisとかBSD系でも動かないといけないので、どうしたもんかなあ。
Similar Posts:
- Newer: jemallocの_malloc_preforkのバグ?
- Older: MPICH2内のコードを変える時のTIPS
Comments:0
Trackbacks:0
- Trackback URL for this entry
- http://kzk9.net/blog/2009/09/deadlock_on_process_builder.html/trackback
- Listed below are links to weblogs that reference
- Java ProcessBuilderでデッドロック from moratorium
