Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

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単体では問題なくアクセスできるので、Apachemod_pythonPython辺りの組み合わせに何かあるのかなぁと調べてみると、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のバージョンを合わせる事にしたのですが、


Updating System Expat Version

Because 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.

とのことで、Apache側のexpatのバージョン(1.95.5)をPython側(1.95.8)に合わせる事にしました。

$ 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再起動したところ、何事もなかったかのように動作するようになりました。


ちなみに、うまくいった環境ですが、rpmPython・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 106 13:01 /usr/local/apache2/lib/libexpat.a
-rwxr-xr-x 1 root root    807 106 13:01 /usr/local/apache2/lib/libexpat.la
lrwxrwxrwx 1 root root     17 106 13:01 /usr/local/apache2/lib/libexpat.so -> libexpat.so.0.1.0
lrwxrwxrwx 1 root root     17 106 13:01 /usr/local/apache2/lib/libexpat.so.0 -> libexpat.so.0.1.0
-rwxr-xr-x 1 root root 304852 106 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
#