JavaScript の時間が UTC になってしまう問題 #38

公開日: 2012-05-16


同僚から V8 [1] をデバッグするにはどうしたらいいのか、という質問を受けた。そんなことやったことないから知らん、と答えたものの、そもそもなんでV8をデバッグしようとしているか気になったので聞いてみると、Chromium OS 上で JavaScript の時間が UTC (ロンドンの時間) になってしまう問題を調べているとのこと。

おもしろそうなので見せてもらうと、たしかに JavaScript コンソールから new Date を評価してやると時間がずれている。ああ、タイムゾーンってなんか zonefile とかいうやつを見るはずなんだけど、その辺がおかしいんじゃないの?と当たりをつけて適当に調べてみたものの、ターミナルから date コマンドを実行すれば正しい結果が返ってくるし、/etc や /usr/share なんかを見ても正しいファイルを使っているように見える。何がおかしいんだろう?

ふと思い当たったのは、JavaScript はレンダラープロセスの中で動いていて、レンダラープロセスはサンドボックスで chroot の中に入っているから、そもそも /usr/share の下のファイルなんか読めないはず、ということ。じゃあ、もしかして昔からこれずっと壊れていたのかも?

そう思って、少し古いバージョンを試してみると、 new Date は正しい時間を返してくる。ということは最近壊れたらしい。じゃあ今まではそもそもどうやって動いていたの?ということを識者に聞いてみると、太古のバグのURL [2] を教えてくれた。

ざっと眺めてみると、レンダラープロセス内では glibc の localtime, localtime_r の呼び出しを乗っ取って(サンドボックスを外しているときは元の関数を dlopen/dlsym を使って呼べるようにして)、別のプロセスにIPCして時間を教えてもらっているということがわかった。しかも、よく読むと、NVIDIA のライブラリがリンクされると、この仕組みが動かなくて、さらなるハックが必要になった、みたいな歴史まで書かれていた(NVIDIAのコードが dlsym を横取りしていたらしい...)。おそろしい世界である。

で、どうもまたこの乗っ取り作戦が壊れているっぽいんだけど、なんででしょうねえー、glibc の何かが変わったのかも?みたいなところまで話したところで私は時間切れ。

しばらくしてメールをチェックしてみると、最近、システム全体を 64ビット化したのが影響しているのかも?そのとおり!localtime, localtime_r の実体は 64ビットだと localtime64, localtime64_r という名前に変わっているから、こいつらも乗っ取ればOK、という解決策が発見されて、パッチも出来上がっていた。

プロセス分離やらサンドボックスやらを動かすのは大変なもんだなと思った出来事であった。

[1] http://code.google.com/p/v8/ - Chrome や Node で使われている JavaScript Engine
[2] http://crbug.com/16800

Satoru Takabayashi