OSX+PostgreSQL+Railsな環境でhttpsにアクセスするとSegmentation Faultする
前回のエントリではWindowsがどうのと言っていましたが、TestやWEBrickの起動が遅すぎて話にならないのでMacに環境を再構築しました。
PHPもとても遅いのだけれど、それはOSのFile I/Oの速度が大きく影響しているっぽいです。
それはさておき、OSXでWEBrickを立ち上げてTwitterにアクセスしたところ、
/Users/kent/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/net/http.rb:678: [BUG] Segmentation fault
というエラーが出てきました*1。ソースをみるとhttpsソケットを作ってconnectしようとして落ちているようです。Windowsでは正しく動作していたプログラムだったので、理由がわからず。Rubyの所為かと思ってp0からheadリビジョンまで入れて試してみましたが何も変わらず。むしろ何も変わらないので、ほかに原因があるんだなとおもって探していると、
[Ruby 1.9-Bug#4373][Open] http.rb:677: [BUG] Segmentation fault - Ruby Forum
に行き当たりました。というか、これしか情報源ないの?的な。
結論から言うと、
portsやOne Click InstallerでインストールしたPostgreSQLが使っているOpenSSLのバージョンが、Rubyの使っているものよりも古くてかつ先に読み込まれているので、RubyからTwitterのHTTPSで提供されているサービスにアクセスしようとしたときに、落ちる。
ということのようです。
上のサイトにあるようにして、使っているライブラリを確認してみると
rails console ruby-1.9.2-p180 :001 > require 'openssl' => nil ruby-1.9.2-p180 :002 > system "otool -L #{$LOADED_FEATURES.grep(/openssl.bundle/).join (' ')}"
とするとRubyで利用しようとしている読み込まれているopensslのバージョンがわかります。結果は
/Users/kent/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/x86_64-darwin10.7.0/openssl.bundle: /Users/kent/.rvm/rubies/ruby-1.9.2-p180/lib/libruby.1.9.1.dylib (compatibility version 1.9.1, current version 1.9.1) /usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8) /usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.10) /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0) => true
とでて、0.9.8を読み込もうとしています。
対するPostgreSQLは、
bash-3.2$ otool -L /Library/PostgreSQL/9.0/lib/libpq.dylib /Library/PostgreSQL/9.0/lib/libpq.dylib: libpq.5.dylib (compatibility version 5.0.0, current version 5.3.0) /usr/lib/libssl.0.9.7.dylib (compatibility version 0.9.7, current version 0.9.7) /usr/lib/libcrypto.0.9.7.dylib (compatibility version 0.9.7, current version 0.9.7) /System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 5.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.4)
で、0.9.7でした。この違いがエラーを引き起こしているようです。
で、解決策ですが、
- developmentではsqlite3を使う
- 自分でPostgreSQLのソースコードを持ってきてインストールする
1は後ろ向きですが、まぁSQLのチューニングが必要だとかの特段の理由がなければ開発環境でPostgreSQLを使う理由はないですし。それでもいいかなと思います。
2はPostgreSQLのサイトからtarボールを持ってきてconfigure/make/make installで、デフォルトの位置にインストールされたなら
gem install pg -- --with-pg-dir=/usr/local/pgsql/
とすればいいです。デフォルトでconfigureするとwithout opensslなので、opensslサポートが必要ならそのようにconfigureすればいいです。
ただ、localhostとの通信にopenssl使う理由もわからないので、必要ないでしょう。
しかし、本当にRuby界隈のみなさんは、PostgreSQL使ってないんだなと感じた出来事でした。
いや、前回の記事ではWindowsが悪いんだ!って言ってたけど、PostgreSQLが過疎ってるだけでした。PostgreSQLいいよ!Postgre!
という訳で、エラーエントリでした。