strace处理库链接错误用例一则

问题:

在某个suse环境下编译完php-5.4.41及memcached扩展后,执行php报错如下,且检查/var/log/php_error.log无错误输出。

# php -v
Floating point exception  

/var/log/messages有如下输出,然而并没有什么卵用。

kernel: [31353122.745809] php[2231] trap divide error ip:7fcb7a2c165f sp:7fff010bc800 error:0 in ld-2.4.so[7fcb7a2b9000+1b000]  

排查:

这种几乎没有任何有用输出的故障,难道我们就没办法治它了吗?让我们祭出本文的主角:strace

# strace php -v
...
省略了一大波输出,从最后看起。
open("/usr/local/lib/libmemcached.so.11", O_RDONLY) = 3  
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 I\0\0\0"..., 832) = 832  
fstat(3, {st_mode=S_IFREG|0755, st_size=1296470, ...}) = 0  
mmap(NULL, 2292344, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f126ce7d000  
madvise(0x7f126ce7d000, 2292344, MADV_SEQUENTIAL|0x1) = 0  
mprotect(0x7f126ceac000, 2097152, PROT_NONE) = 0  
mmap(0x7f126d0ac000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2f000) = 0x7f126d0ac000  
close(3)                                = 0  
--- SIGFPE (Floating point exception) @ 0 (0) ---
+++ killed by SIGFPE +++
Process 23188 detached  

执行流程先是打开/usr/local/lib/libmemcached.so.11,然后将其映射入虚拟内存,接着执行这个库的代码段,就在这时候收到了“Floating point exception”。

从上面的输出可以看出极大可能是memcached扩展模块出的问题了。尝试在/etc/php.ini中注释掉memcached后果然没有报错了,这就说明了问题出在memcached。

找了下之前编译php-5.4.25的文档,原来用的包是memcached-2.1,现在用的是memcache-2.2。

怀疑可能是包的兼容问题,于是拿2.1版本过来重新编译替换,但是依然是“Floating point exception”的报错。

回过头来想了下,是libmemcached.so这个动态库出的问题,memcached是加载该动态库的,应该是去找libmemcached的问题,而不是找memcached。

# ldd /usr/local/services/php/lib/php/extensions/no-debug-zts-20100525/memcached.so                  
        linux-vdso.so.1 =>  (0x00007fff5d5ff000)
        libmemcached.so.11 => /usr/local/lib/libmemcached.so.11 (0x00007f12bc4b3000)
        以下省略

再在正常的suse环境(还在使用php-5.2.17)下strace php -v,对应的输出是这样子的:

open("/usr/lib64/libmemcached.so.11", O_RDONLY) = 3  

然后在这个问题环境中查看,也有这个文件,什么情况? 先分别查看下这两个库文件属于哪个包:

# rpm -qf /usr/lib64/libmemcached.so.11
libmemcached11-1.0.10-1.1  
# rpm -qf /usr/local/lib/libmemcached.so.11
php_memcached-2.1.0-1  

然后再看下源上面的包:

# zypper se libmemcached
Restoring system sources...  
Parsing metadata for update...  
Parsing metadata for SUSE10-SP4...  
S | Catalog | Type    | Name               | Version    | Arch  
--+---------+---------+--------------------+------------+-------
i | update  | package | libmemcached       | 1.0.10-1.1 | x86_64  
i | update  | package | libmemcached-devel | 1.0.10-1.1 | x86_64  
i | update  | package | libmemcached11     | 1.0.10-1.1 | x86_64  
i | update  | package | libmemcachedutil2  | 1.0.10-1.1 | x86_64  

看来libmemcached11的/usr/lib64/libmemcached.so.11才是正房啊。那又是为什么/usr/local/lib/libmemcached.so.11这个小妾排在了正房的前面呢? 看下/etc/ld.so.conf

# cat /etc/ld.so.conf
/usr/X11R6/lib64/Xaw3d
/usr/X11R6/lib64
/usr/X11R6/lib/Xaw3d
/usr/X11R6/lib
/usr/x86_64-suse-linux/lib
/usr/local/lib
/opt/kde3/lib
/opt/gnome/lib
/lib64
/lib
/usr/lib64
/usr/lib
/usr/local/lib64
以下省略

看来是这个原因了。


2个解决方法:
  1. 确认没有使用php_memcached后卸载该rpm包;
  2. 调整/etc/ld.so.conf的顺序后执行ldconfig重新生成ld.so.cache(不建议,可能会导致别的应用读错动态库)