linux32bit trader运行加载thosttraderapi.so出错 SIGSEGV, Segmentation fault 最近把win上跑的ctp接口挪到linux32上 行情md可以跑,一切正常. 交易trader就运行错误, gdb后发现是thosttraderapi.so在程序加载时内部调用了0xb7b9e4ce in OPENSSL_cpuid_setup (). 出现Segmentaion fault 我折腾了一个月还是没得头绪,系统是32位的 gentoo 和 centos 6都试过, thosttraderapi.so 版本用过2010年的,还有2014年的v6.3.6都是同样的问题.现在行情在linux上跑,下单在vista上跑, 一直不爽.
看来没人碰到这个问题, objdump -S -d thosttraderapi.so 先把反汇编列一下. 000864ec <_init>: 864ec: 55 push %ebp 864ed: 89 e5 mov %esp,%ebp 864ef: 83 ec 08 sub $0x8,%esp 864f2: e8 89 46 00 00 call 8ab80 <call_gmon_start> 864f7: e8 34 47 00 00 call 8ac30 <frame_dummy> 864fc: e8 bf af 0f 00 call 1814c0 <OPENSSL_cpuid_setup> 86501: e8 8a df 1b 00 call 244490 <__do_global_ctors_aux> 86506: c9 leave 86507: c3 ret init 之后就直接 call OPENSSL_cpuid_setup,跑到 001814c0 对应内容如下. 001814c0 <OPENSSL_cpuid_setup>: 1814c0: 48 dec %eax 1814c1: 89 5c 24 f0 mov %ebx,-0x10(%esp) 1814c5: 48 dec %eax 1814c6: 89 6c 24 f8 mov %ebp,-0x8(%esp) 1814ca: 48 dec %eax 1814cb: 83 ec 28 sub $0x28,%esp 1814ce: 8b 05 d8 80 39 00 mov 0x3980d8,%eax (出错位置) 1814d4: 85 c0 test %eax,%eax 1814d6: 74 0f je 1814e7 <OPENSSL_cpuid_setup+0x27> 1814d8: 48 dec %eax 1814d9: 8b 5c 24 18 mov 0x18(%esp),%ebx 1814dd: 48 dec %eax ... ...后面不列。 再用gdb调试,在OPENSSL_cpuid_setup 前设置断点, 单步执行了7步出错. 如上标注, 以下为gdb输出。 Breakpoint 1, 0xb7b9e4c0 in OPENSSL_cpuid_setup () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so (gdb) si 0xb7b9e4c1 in OPENSSL_cpuid_setup () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so (gdb) si 0xb7b9e4c5 in OPENSSL_cpuid_setup () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so (gdb) si 0xb7b9e4c6 in OPENSSL_cpuid_setup () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so (gdb) si 0xb7b9e4ca in OPENSSL_cpuid_setup () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so (gdb) si 0xb7b9e4cb in OPENSSL_cpuid_setup () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so (gdb) si 0xb7b9e4ce in OPENSSL_cpuid_setup () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so (gdb) si Program received signal SIGSEGV, Segmentation fault. 0xb7b9e4ce in OPENSSL_cpuid_setup () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so
尝试一下午夜屠夫直接修改thosttraderapi.so文件控制跳转。 先把反汇编AT&T格式换成intel格式. 001814c0 <OPENSSL_cpuid_setup>: 1814c0: 48 dec eax 1814c1: 89 5c 24 f0 mov DWORD PTR [esp-0x10],ebx 1814c5: 48 dec eax 1814c6: 89 6c 24 f8 mov DWORD PTR [esp-0x8],ebp 1814ca: 48 dec eax 1814cb: 83 ec 28 sub esp,0x28 1814ce: 8b 05 d8 80 39 00 mov eax,DWORD PTR ds:0x3980d8 (出错) 1814d4: 85 c0 test eax,eax 1814d6: 74 0f je 1814e7 <OPENSSL_cpuid_setup+0x27> 1814d8: 48 dec eax 1814d9: 8b 5c 24 18 mov ebx,DWORD PTR [esp+0x18] 1814dd: 48 dec eax 1814de: 8b 6c 24 20 mov ebp,DWORD PTR [esp+0x20] 1814e2: 48 dec eax 1814e3: 83 c4 28 add esp,0x28 1814e6: c3 ret 1814e7: 48 dec eax 1814e8: 8d 3d 78 db 0c 00 lea edi,ds:0xcdb78 1814ee: c7 05 b4 80 39 00 01 mov DWORD PTR ds:0x3980b4,0x1 1814f5: 00 00 00 这下好看多了,把 出错行的代码改成6个nop操作 1814ce: 8b05d8803900 mov eax,DWORD PTR ds:0x3980d8 在thosttraderapi.so文件类找 1814c0: 48895C24F048896C24F84883EC288B05D8803900 改成 1814c0: 48895C24F048896C24F84883EC28909090909090 从新rebuild 运行,还是 Program received signal SIGSEGV, Segmentation fault. 0xb7b9e381 in CRYPTO_set_id_callback () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so 在这里出错 00181380 <CRYPTO_set_id_callback>: 181380: 48 dec eax 181381: 89 3d 49 82 39 00 mov DWORD PTR ds:0x398249,edi (出错) 181387: c3 ret 181388: 0f 1f 84 00 00 00 00 nop DWORD PTR [eax+eax*1+0x0] 18138f: 00 再把je 改成jne,不退出 跳到 1814e7 开始运行 1814d0: 9090909085C0740F 改成 1814d0: 9090909085C0750F Program received signal SIGSEGV, Segmentation fault. 0xb7b9e4ee in OPENSSL_cpuid_setup () from /home/prog/ctp/td32_6.3.6/lib/thosttraderapi.so 还是错 1814ee: c7 05 b4 80 39 00 01 mov DWORD PTR ds:0x3980b4,0x1 (出错) 看来所有错误都是指向 对DS区域的读写 DWORD PTR ds:0x398___ 怎么办?
据说官网提供下载的32位版本误链接了64位库导致运行时崩溃,请试下这个版本:http://itfin.f3322.org/pub/ctp32.7z,是我们要求CTP重新提供的,版本是6.3.0,略老一点。
上面提供的版本可以用了,我手上的版本不是64的问题,出错全是访问 DWORD PTR ds:0x398 的代码段,所在的函数都是openssl有关的。 001812b0 <CRYPTO_get_dynlock_lock_callback>: 001812e0 <CRYPTO_set_dynlock_lock_callback>: 001812c0 <CRYPTO_get_dynlock_destroy_callback>: 001812f0 <CRYPTO_set_dynlock_destroy_callback> 00181310 <CRYPTO_get_add_lock_callback>: 00181320 <CRYPTO_set_add_lock_callback>: 00181330 <CRYPTO_THREADID_set_callback>: 00181350 <CRYPTO_THREADID_get_callback>: 00181370 <CRYPTO_get_id_callback>: 00181380 <CRYPTO_set_id_callback>: 001812d0 <CRYPTO_set_dynlock_create_callback>: 00181300 <CRYPTO_get_locking_callback>: 001814c0 <OPENSSL_cpuid_setup>: 全都是和和OPENSSL有关的调用,在网上一个的crypto.h里面有定义,代码在cryptlib.c里面找到。
看so的依存关系,ssl应该是一起做到thosttraderapi.so里面了,没有再调用其他库, 目前用楼上提供的v6.3.0, 过几天闲下来再好好对比一下两个版本的看看能不能发现问题. ldd thosttraderapi.so linux-gate.so.1 (0xffffe000) libpthread.so.0 => /lib/libpthread.so.0 (0xb71c7000) librt.so.1 => /lib/librt.so.1 (0xb71be000) libdl.so.2 => /lib/libdl.so.2 (0xb71b9000) libstdc++.so.6 => /usr/lib/gcc/i686-pc-linux-gnu/4.8.4/libstdc++.so.6 (0xb70d1000) libm.so.6 => /lib/libm.so.6 (0xb708b000) libgcc_s.so.1 => /usr/lib/gcc/i686-pc-linux-gnu/4.8.4/libgcc_s.so.1 (0xb706e000) libc.so.6 => /lib/libc.so.6 (0xb6ed3000) /lib/ld-linux.so.2 (0xb7709000)
算了,我系统上还要升级mysql apache virtualbox R perl 一堆东西,我现在觉得能跑就不想换了,总结过去经验,我花在折腾系统和程序之间的配合的时间上远多于花在策略的开发和backtest上。