Apache+mod_python+tracでsegfaultする件
trac絡みのネタが続きます。。。
Trac-0.11b1を導入した訳なんですが、別の環境では
$ trac-admin /path/to/trac_project upgrade $ trac-admin /path/to/trac_project wiki upgrade
した後にアクセスすると、Apache(2.0.63/2.2.6)がSegmentation Faultするようになってしまいました。tracd単体では問題なくアクセスできるので、Apacheとmod_python、Python辺りの組み合わせに何かあるのかなぁと調べてみると、GoogleCodeに情報がありました。
キーワードは「Mismatch In Versions Of Expat」。ということで、早速確認。
$ ldd /usr/local/apache2/bin/httpd | grep expat libexpat.so.0 => /usr/lib/libexpat.so.0 (0x003e0000) $ strings /usr/lib/libexpat.so.0 | grep expat_ expat_1.95.5 $ python Python 2.4.4 (#1, Jan 23 2008, 14:10:57) [GCC 3.2.3 20030502 (Red Hat Linux 3.2.3-52)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import pyexpat >>> pyexpat.version_info (1, 95, 8) >>> $
と、微妙ですが確かに違いました。で、環境変数LD_PRELOADを使って確認してみましたが、
$ LD_PRELOAD=/usr/lib/libexpat.so python Python 2.4.4 (#1, Jan 23 2008, 14:57:59) [GCC 3.4.6 20060404 (Red Hat 3.4.6-9)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import pyexpat Segmentation fault $
。。。見事に「11」が俺を貫きましたorz ビンゴのようです。
ということで、expatのバージョンを合わせる事にしたのですが、
とのことで、Apache側のexpatのバージョン(1.95.5)をPython側(1.95.8)に合わせる事にしました。
Updating System Expat VersionBecause the version of the "expat" library embedded within the "pyexpat" module is shipped as source code within the Python distribution, it can be hard to replace it. The preferred approach to resolving the mismatch is therefore to replace/update the version of the "expat" library that is used by Apache.
$ wget http://nchc.dl.sourceforge.net/sourceforge/expat/expat-1.95.8.tar.gz $ tar zxf expat-1.95.8.tar.gz -C /usr/local/src/ $ cd /usr/local/src/expat-1.95.8/ $ ./configure $ make $ sudo make install $ sudo vi /usr/local/apache2/bin/envvars $ diff /usr/local/apache2/bin/envvars-std /usr/local/apache2/bin/envvars 21c21 < LD_LIBRARY_PATH="/usr/local/apache2/lib:$LD_LIBRARY_PATH" --- > LD_LIBRARY_PATH="/usr/local/apache2/lib:/usr/local/lib:$LD_LIBRARY_PATH" $ sudo /usr/local/apache2/bin/apachectl stop $ sudo /usr/local/apache2/bin/apachectl startssl $
こんな感じでexpatをインストール・設定・Apache再起動したところ、何事もなかったかのように動作するようになりました。
ちなみに、うまくいった環境ですが、rpmでPython・libexpatをインストールし、Apache(2.0.61)もそのlibexpatをloadしていたので、*たまたま*うまく動いていたようです。
$ ldd /usr/local/apache2/bin/httpd | grep expat libexpat.so.0 => /usr/lib/libexpat.so.0 (0x00831000) $ strings /usr/lib/libexpat.so.0 | grep expat_ expat_1.95.7 $ python Python 2.3.4 (#1, Dec 11 2007, 05:27:57) [GCC 3.4.6 20060404 (Red Hat 3.4.6-9)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import pyexpat >>> pyexpat.version_info (1, 95, 7) >>> $
なので、「rpmなら全てrpm」「ソースなら全てソース」と揃えた方が間違いがないと思います。
まあ、今日はこんな感じで1日潰れました。。。orz
追記(2009/10/16 14:38)
インストールし直すよりも、ライブラリ側のシンボリックリンクを張り替えた方が早いですね。以下は、pythonが使っているlibexpatが/lib/libexpat.so.0の場合。ただ、Apacheをバージョンアップする際にアレですが。。。
# ldd /usr/local/apache2/bin/httpd | grep expat libexpat.so.0 => /usr/local/apache2/lib/libexpat.so.0 (0x002f1000) # strings /usr/local/apache2/lib/libexpat.so.0 | grep expat_ expat_1.95.2 # ll /usr/local/apache2/lib/libexpat.* -rw-r--r-- 1 root root 344700 10月 6 13:01 /usr/local/apache2/lib/libexpat.a -rwxr-xr-x 1 root root 807 10月 6 13:01 /usr/local/apache2/lib/libexpat.la lrwxrwxrwx 1 root root 17 10月 6 13:01 /usr/local/apache2/lib/libexpat.so -> libexpat.so.0.1.0 lrwxrwxrwx 1 root root 17 10月 6 13:01 /usr/local/apache2/lib/libexpat.so.0 -> libexpat.so.0.1.0 -rwxr-xr-x 1 root root 304852 10月 6 13:01 /usr/local/apache2/lib/libexpat.so.0.1.0 # mv /usr/local/apache2/lib/libexpat.so.0 /usr/local/apache2/lib/libexpat.so.0_ # ln -s /lib/libexpat.so.0 /usr/local/apache2/lib/ # ldd /usr/local/apache2/bin/httpd | grep expat libexpat.so.0 => /usr/local/apache2/lib/libexpat.so.0 (0x009b1000) # strings /usr/local/apache2/lib/libexpat.so.0 | grep expat_ expat_1.95.8 #
追記2(2009/10/16 14:55)
いやいや、envvarsにLD_PRELOADを定義しちゃえばよくね?
# echo "export LD_PRELOAD=/lib/libexpat.so.0" >> /usr/local/apache2/bin/envvars #