FreeBSD
Apache2.4

FreeBSD11 + apache24 でmod_uploader

タイトルの構成でmod_uploaderの導入でハマったので備忘録的に。

このサーバではいろいろ動かしてますが、そのうちの一つに某MMORPGのギルドメンバー向けに
内輪のファイル共有のためのアップローダーをmod_uploaderを利用して設置してます。
今回はまったのはこいつ

きっかけはapacheのアップデート

pkgでパッケージ管理してると知ってると思いますが、pkgで提供されるバイナリパッケージでは
デフォルトのバージョンが更新されることがあります。
apacheの場合は以前は2.2だったところ、2.4に更新され、それにあわせ各種モジュールのパッケージもapache2.4に合わせたものに更新されました。

面倒だったので(おい)放置してたんですが、しばらく前に10-RELEASEから11-RELEASEに更新したときに改めて警告でたので、更新やることにしました。

とりあえずapacheの更新

# pkg install apache24

で、apache2.2と2.2用モジュールのパッケージが削除され、apache2.4がインストールされます。
apacheだけだとこんな感じになりますね


Installed packages to be REMOVED:
        apache22-2.2.34_1

New packages to be INSTALLED:
        apache24: 2.4.29

Number of packages to be removed: 1
Number of packages to be installed: 1

The process will require 9 MiB more space.

Proceed with this action? [y/N]:

apache22依存のモジュールは削除だけしてインストールしてくれないっぽいので
必要な人は別途pkg installしましょう
あと、2.2と2.4でconfig作法変わる部分がありますがそのへんはぐぐればいろいろ出るので割愛

コンパイルのお時間

いきなりコンパイルでエラー

以前に導入したときの作業ファイルがそのままのこってたので、

# gmake clean
# ./configure
# gmake

でいけるとおもったんだが、エラー発生して止まる。

In file included from mod_uploader.cpp:57:0:
../include/ApacheResponse.h: In static member function 'static const char* ApacheResponse::get_remote_ip(ApacheResponse::Handle*)':
../include/ApacheResponse.h:143:31: error: 'conn_rec {aka struct conn_rec}' has no member named 'remote_ip'; did you mean 'remote_host'?
         return r->connection->remote_ip;
                               ^~~~~~~~~
../include/ApacheResponse.h: In static member function 'static apr_sockaddr_t* ApacheResponse::get_remote_addr(ApacheResponse::Handle*)':
../include/ApacheResponse.h:160:31: error: 'conn_rec {aka struct conn_rec}' has no member named 'remote_addr'; did you mean 'remote_host'?
         return r->connection->remote_addr;

ぐぐってみたところ、apache2.2と2.4でなんか変わったらしい。
ついでにmod_uploaderの3.2.0ならapache2.4に対応してるとか見つかったのでソースひろってくる。
(上記エラーはmod_uploader3.1.1で発生)
FreeBSDの動作環境がapache20 or apache22になってるけど、まぁなんとかなるだろ。
なりませんでした

今度はsegmentation fault

ということで、mod_uploader3.2.0のソースを展開して、configure & makeしたところ、今度はsegfaultが発生。

Compiling UploaderConfig.cpp
/usr/local/bin/libtool --silent --mode=compile --tag=CXX g++ -prefer-pic -DUPLOADER_TYPE_APACHE -DEAPI -c -I../include -I /usr/local/include/apache24  -isystem /usr/local/include/apr-1 -isystem /usr/local/include -O3 -MMD -Wall -Wextra -Wformat=2 -Wdisabled-optimization -Wfloat-equal -Wpointer-arith -Wcast-align -Wno-unused-parameter -fno-rtti -pipe   -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wpointer-arith -Wfloat-equal -Wstrict-aliasing -ftracer -fforce-addr -fvisibility=hidden -o UploaderConfig.o UploaderConfig.cpp

g++: internal compiler error: Segmentation fault (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
gmake[1]: *** [GNUmakefile.dep:196: UploaderConfig.o] Error 1
gmake[1]: Leaving directory '/root/mod_uploader-3.2.0/src'
gmake: *** [GNUmakefile:66: apache-module] Error 2

さすがにsegfaultは原因すぐわかりそうにないなぁ、ということで、ことのきはapache2.2を入れ直して元の状況に戻した。

クリーンインストール状態で検証

仮想マシンを用意

対象のサーバ、8-RELEASEあたりからupdate繰り返している&いろいろ入れたり消したりしまくっていて、こいつでイチから調査とかきつい思ったので、VmwarePlayerで仮想マシンを作って、11.1-RELEASEをクリーンインストールした環境を作った。
で、動作環境に書いてあるものだけをpkgでインストール。

# pkg install apache24
# pkg install ImageMagick

configureでlibtoolがないと怒られたので、libtoolも追加でインストール。
configureとおったのでmakeしたところ、
正常にコンパイル終了した
余計にわけわからなくなってきたが、気を取り直して実機と比較してみたところ、使用しているコンパイラが違っていた。
具体的には、実機のほうはgccが入っているが、仮想マシン環境のほうには入れてなかった。

コンパイルはできたものの

ということで、実機のほうの環境からgccを取り除いてみた

# pkg remove gcc gcc6 gcc-ecj

で、あらためてconfigure&makeしたところ、正常にコンパイル完了した。

apache起動せず

作成された.soファイルを設置し、モジュール読み込みの設定をしてconfigtestしたところ、こんな状態に。

# /usr/local/etc/rc.d/apache24 configtest
Performing sanity check on apache24 configuration:
httpd: Syntax error on line 535 of /usr/local/etc/apache24/httpd.conf: Syntax error on line 1 of /usr/local/etc/apache24/Includes/mod_uploader.conf: Cannot load libexec/apache24/mod_uploader.so into server: /usr/local/libexec/apache24/mod_uploader.so: Undefined symbol "libiconv"

どうなってんだゴルァと毒づきながらlibiconvとやらの状態いろいろ確認

# pkg info | grep iconv
libiconv-1.14_11               Character set conversion library
# pkg info -l libiconv
libiconv-1.14_11:
        /usr/local/bin/iconv
        /usr/local/include/iconv.h
        /usr/local/include/libcharset.h
        /usr/local/include/localcharset.h
        /usr/local/lib/charset.alias
        /usr/local/lib/libcharset.a
        /usr/local/lib/libcharset.so
        /usr/local/lib/libcharset.so.1
        /usr/local/lib/libcharset.so.1.0.0
        /usr/local/lib/libiconv.a
        /usr/local/lib/libiconv.so
        /usr/local/lib/libiconv.so.2
        /usr/local/lib/libiconv.so.2.5.1
        /usr/local/man/man1/iconv.1.gz
        /usr/local/man/man3/iconv.3.gz
        /usr/local/man/man3/iconv_close.3.gz
        /usr/local/man/man3/iconv_open.3.gz
        /usr/local/man/man3/iconv_open_into.3.gz
        /usr/local/man/man3/iconvctl.3.gz
        /usr/local/share/doc/libiconv/iconv.1.html
        /usr/local/share/doc/libiconv/iconv.3.html
        /usr/local/share/doc/libiconv/iconv_close.3.html
        /usr/local/share/doc/libiconv/iconv_open.3.html
        /usr/local/share/doc/libiconv/iconv_open_into.3.html
        /usr/local/share/doc/libiconv/iconvctl.3.html
        /usr/local/share/licenses/libiconv-1.14_11/GPLv3
        /usr/local/share/licenses/libiconv-1.14_11/LICENSE
        /usr/local/share/licenses/libiconv-1.14_11/catalog.mk

includeとlibのファイル確認したがちゃんと存在する。
んじゃ生成物はどうなってんのと見てみると

# ldd /usr/local/libexec/apache24/mod_uploader.so
/usr/local/libexec/apache24/mod_uploader.so:
        libm.so.5 => /lib/libm.so.5 (0x801241000)
        libapr-1.so.0 => /usr/local/lib/libapr-1.so.0 (0x80146c000)
        libcrypt.so.5 => /lib/libcrypt.so.5 (0x8016a4000)
        libthr.so.3 => /lib/libthr.so.3 (0x8018c3000)
        libc++.so.1 => /usr/lib/libc++.so.1 (0x801aeb000)
        libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x801db2000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x801fd0000)
        libc.so.7 => /lib/libc.so.7 (0x800824000)

libiconv.soがいません。なんでリンクしてねーんだよってことでconfigureファイルとGNUmakefileをいろいろ調べたところ、iconvライブラリがあれば、リンカオプションに'-liconv'が追加されるはずなんだが、自分の環境でconfigureしたやつはこいつが入ってない。
configureで--with--なんちゃらしないとダメかなとconfigure --helpしてみたがiconv関係では存在しない模様

やっとこさ解決

状況はわかったが、さてどうしたもんかと思ったが、そういやconfigureスクリプトって環境変数みたよな、と思い出した。
そこで環境変数LDFLAGSを設定、/usr/local/libを参照するようにしてconfigureしてみた。

# setenv LDFLAGS -L/usr/local/lib
# ./configure
(略)
# gmake
(略)
# ldd ./mod_uploader.so
./mod_uploader.so:
        libm.so.5 => /lib/libm.so.5 (0x801241000)
        libapr-1.so.0 => /usr/local/lib/libapr-1.so.0 (0x80146c000)
        libcrypt.so.5 => /lib/libcrypt.so.5 (0x8016a4000)
        libthr.so.3 => /lib/libthr.so.3 (0x8018c3000)
        libc++.so.1 => /usr/lib/libc++.so.1 (0x801aeb000)
        libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x801db2000)
        libiconv.so.2 => /usr/local/lib/libiconv.so.2 (0x801fd0000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x8022cb000)
        libc.so.7 => /lib/libc.so.7 (0x800824000)

やりました
こいつをapacheのモジュールディレクトリにもってってconfigtestしたら今回は問題なし、起動もOKとなりました。
いやほんと、こんなにはまるとは思ってもなかったわ…