Node.js v4.3をv4.8にアップデートしたところsegmentation faultが多発するようになった。
/var/log/messages を見ると以下のようなログが残っている
May 15 08:51:32 hostname-hoge001 kernel: node[11262]: segfault at a764a503788 ip 0000000000aecd71 sp 00007ffd5a48b380 error 4 in node[400000+1376000]
error 4、「ユーザーモードでの読み込み時にページが見つからなかった」らしい。過去にメモリ不足で発生したことがあったが、今回はメモリは十分足りている。全く原因がわからないのでコアダンプを取って調べる事にした。
コアを吐くように ulimit -c unlimited を呼び出してからNode.jsプロセスを起動するように起動スクリプトを修正。
本番環境にリリースし、プロセスが落ちてコアを吐くのを待つ。3日ほど放置してコアダンプを収穫。ちなみにこのシステムはNode.jsプロセスの1つや2つが落ちても問題ない設計になっている。
(gdb) bt #0 0x0000000000aecd71 in v8::internal::MarkCompactCollector::ProcessWeakCollections() () #1 0x0000000000af50d4 in v8::internal::MarkCompactCollector::MarkLiveObjects() () #2 0x0000000000af5b71 in v8::internal::MarkCompactCollector::CollectGarbage() () #3 0x0000000000aaccf0 in v8::internal::Heap::MarkCompact() () #4 0x0000000000ac4718 in v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) () #5 0x0000000000ac4cb9 in v8::internal::Heap::CollectGarbage(v8::internal::GarbageCollector, char const*, char const*, v8::GCCallbackFlags) () #6 0x0000000000ac56c1 in v8::internal::Heap::HandleGCRequest() () #7 0x0000000000a6131c in v8::internal::StackGuard::HandleInterrupts() () #8 0x0000000000c96f8b in v8::internal::Runtime_StackGuard(int, v8::internal::Object**, v8::internal::Isolate*) () #9 0x0000065d13a06355 in ?? () #10 0x0000000600000007 in ?? () #11 0x0000000000000000 in ?? ()
(gdb) bt #0 0x0000000000c7a38e in v8::internal::Runtime_WeakCollectionGet(int, v8::internal::Object**, v8::internal::Isolate*) () #1 0x0000329d23a0963b in ?? () #2 0x0000329d23a09581 in ?? () #3 0x00007ffd20be0830 in ?? () -- 省略 -- #78 0x00000000030b7f60 in ?? () #79 0x00000000030b5fc0 in ?? () #80 0x00007ffd20be0b90 in ?? () #81 0x0000000000b9227f in v8::internal::KeyedLoadIC_Miss(int, v8::internal::Object**, v8::internal::Isolate*) ()
デバッグビルドではないので行番号は取れないが、Weak Collectionの処理でエラーになっている事がわかった。確かにアプリケーションのソースコードを見るとWeakMapを使っている箇所がある。
さて、次はV8のソースを確認。まずNode.jsに組み込まれたV8のバージョンを調べる。
$ node -p process.versions.v8 4.5.103.45
Node.js v4.3のV8のバージョンは4.5.103.35、v4.8は4.5.103.45である。しかしgitリポジトリに4.5.103.45というタグがないため、V8にどのような変更が加えられたのか分からない。まぁ、変更点が分かったところで弱参照オブジェクトのGCなどコミッタ級の知識がなければ対処不能レベルだろうから、V8の変更点を追うのは一旦あきらめる。
一応、ここ https://nodejs.org/download/release/v4.8.0/ のtarballには V8のソースも付いているので調べることはできる。
Node.jsを6系にアップデートすれば直りそうな気がするが、今は6系で動作検証する余裕がないのでWeakMapを使わないようにしてリリースした。さて直るかな?