KyotoTycoon+LuaJIT-2.0にハマる
非常にニッチなハマり方をしてしまいました.
この世でなん人がKyotoTycoon+KyotoCabinetを使い,その中でなん人がLua-5.2ではなくLuaJIT-2.0を使っていることか.
それまで動いていたシステムが,ふと動かなくなりました.
多少作りこんだシステムだったので,何がおかしいのかが分からずそれだけで時間がかかったのですが,最終的に確実に落ちるポイントを発見.
$ ./ktserver -li -scr example/ktscrjsonex.lua 2012-11-22T13:01:46.270057+09:00: [SYSTEM]: ================ [START]: pid=406 2012-11-22T13:01:46.270273+09:00: [SYSTEM]: opening a database: path=: 2012-11-22T13:01:46.270391+09:00: [SYSTEM]: loading a script file: path=example/ktscrjsonex.lua Segmentation fault
ktscrjsonex.luaは,KyotoTycoonに標準で付属されてくるスクリプトです.それがSegmentation fault.
エラーになる場所を特定すべく,gdbでktserverを立ちあげ,実行.
#1 0x00000000005074be in lj_mem_realloc (L=0x0, p=0x40005a20, osz=5455666, nsz=0) at lj_gc.c:803 #2 0x00000000004f06b6 in lj_str_new (L=0x40000378, str=0x400053c8 "luaJIT_BC_json", lenx=<value optimized out>) at lj_str.c:152
ココ→lj_mem_realloc (L=0x0, p=0x40005a20, osz=5455666, nsz=0).
luaのAPIでは,最初の引数でLuaの状態を示すステータス変数が入るのですが,それがL=0x0になっています.
結局は,Luaスクリプトで,全てのrequire()がエラーになることが分かりました.
考えたあげく,KyotoTycoonをLuaJITをくっつけてコンパイルした時に,さり気なく警告が出ているのに気付きました.
g++ -m64 -g -O2 -Wall -fPIC -fsigned-char -g0 -O2 -o ktremotemgr ktremotemgr.o -L. -L/usr/local/proad/dyson/tools/lib -L. -L/usr/local/proad/dyson/tools/lib -L/usr/local/lib -L/usr/lib/lua-5.1 -L/usr/local/lib/lua-5.1 -L/usr/lib/lua -L/usr/local/lib/lua -L/usr/local/proad/dyson/tools/lib -Wl,-rpath-link,.:/usr/local/lib:.:/usr/local/lib::/usr/lib/lua-5.1:/usr/local/lib/lua-5.1:/usr/lib/lua:/usr/local/lib/lua:/usr/local/proad/dyson/tools/lib -Wl,--as-needed -static -lkyototycoon -lkyotocabinet -lluajit-5.1 -lkyotocabinet -llzma -llzo2 -lz -lstdc++ -lresolv -lnsl -ldl -lrt -lpthread -lm -lc ./libkyototycoon.a(ktsocket.o): In function `kyototycoon::Socket::get_host_address(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': ktsocket.cc:(.text+0x1013): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking #================================================================ # Ready to install. #================================================================
「 warning: Using 'getaddrinfo' in statically linked applications requires at runtime」?????
そう,KyotoTycoonのコンパイル時に,configureで--enable-staticを付けると,こうなりました.
逆に,--enable-staticを付けなかったら...全てのエラーが消えました...require()も使えるようになりました.
せっかくなので,KyotoTycoonのconfigureをLuaJIT対応にするパッチを書きました.
使い方はこんな感じです.
$ patch < configure.patch env LDFLAGS='-L/usr/local/lib -llzo2' CPPFLAGS=-I/usr/local/include ./configure --prefix=/usr/local --with-kc=/usr/local --enable-lua
パッチファイルはこんな感じです.
*** configure.orig 2012-05-02 22:04:11.000000000 +0900 --- configure 2012-11-22 14:32:46.000000000 +0900 *************** *** 2248,2254 **** if test "$enable_lua" = "yes" then ! luaver=`lua -e 'v = string.gsub(_VERSION, ".* ", ""); print(v)'` MYCPPFLAGS="$MYCPPFLAGS -D_MYLUA" MYCPPFLAGS="$MYCPPFLAGS -I/usr/include/lua$luaver -I/usr/local/include/lua$luaver" MYCPPFLAGS="$MYCPPFLAGS -I/usr/include/lua -I/usr/local/include/lua" --- 2248,2254 ---- if test "$enable_lua" = "yes" then ! luaver=-`luajit -e 'v = string.gsub(_VERSION, ".* ", ""); print(v)'` MYCPPFLAGS="$MYCPPFLAGS -D_MYLUA" MYCPPFLAGS="$MYCPPFLAGS -I/usr/include/lua$luaver -I/usr/local/include/lua$luaver" MYCPPFLAGS="$MYCPPFLAGS -I/usr/include/lua -I/usr/local/include/lua" *************** *** 3999,4005 **** $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS ! LIBS="-llua $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ --- 3999,4005 ---- $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS ! LIBS="-lluajit $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ *************** *** 4024,4030 **** { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lua_main" >&5 $as_echo "$ac_cv_lib_lua_main" >&6; } if test "x$ac_cv_lib_lua_main" = xyes; then : ! MYCMDLIBS="$MYCMDLIBS -llua" fi as_ac_Lib=`$as_echo "ac_cv_lib_lua$luaver''_main" | $as_tr_sh` --- 4024,4030 ---- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lua_main" >&5 $as_echo "$ac_cv_lib_lua_main" >&6; } if test "x$ac_cv_lib_lua_main" = xyes; then : ! MYCMDLIBS="$MYCMDLIBS -lluajit" fi as_ac_Lib=`$as_echo "ac_cv_lib_lua$luaver''_main" | $as_tr_sh` *************** *** 4034,4040 **** $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS ! LIBS="-llua$luaver $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ --- 4034,4040 ---- $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS ! LIBS="-lluajit$luaver $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ *************** *** 4060,4066 **** { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : ! MYCMDLIBS="$MYCMDLIBS -llua$luaver" fi fi