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)


luaAPIでは,最初の引数で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