解决Rails+Sphinx特定搜索词报错
我在一个Rails应用中使用了sphinx做全文检索(用的是coreseek提供的版本),但在搜索一些词(比如“环境”)时,Rails日志中会有“comparison of Fixnum with nil failed”的错误,Sphinx的query.log/sphinx.log却无任何记录。此问困扰了我很久,也没搜到什么解决方案。今天最终解决了,于是把查找问题的过程,写在这里。 一、问题初析 仅从Rails的报错信息来看,是将一个数字与nil作比较,导致ruby报错(谁再把脚本语言和弱类型语言混在一起我跟他急)。出错的代码在ultrasphinx-1.11/vendor/riddle/lib/riddle/client.rb的433行: 430 header = socket.recv(8) 431 status, version, length = header.unpack(‘n2N’) 432 433 while response.length < length 434 part = socket.recv(length – response.length) 435 response << part if part 436 end 经验证,length是nil导致ruby报错,而length是从431行的header.unpack得到的。进一步debug发现,header是一个空串,也就是说,430行的socket.recv根本没有从服务器获得响应。 最初想得很简单,在header之外用了一个死循环。只要header为空,就继续调用socket.recv。没想到这直接导致ruby进程陷入死循环,也就是说,对某些query,根本无法收到服务器的响应。 二、tcpdump未果 ruby不停报错,于是想到抓包,看看究竟是哪里出问题了。 祭出tcpdump,自己功力不深,感觉dump出的内容极其晦涩,根本无助于定位问题。 三、初试gdb 仔细看了ruby代码后,感觉Riddle中使用的Socket,是对C语言中Socket操作的简单封装,出问题的可能性不大。因此我把目光放在了sphinx的后台服务searchd上面。 服务器上还留有编译时的C++代码,选了几个看看,没能理出头绪。开了gdb也实在不知该从何处下断点。 到此时,我已经到了放弃的边缘。我一直觉得,是自己对Socket不熟悉于是不能深入地追踪此问题。直到想到去查一下dmesg。 四、从coredump找到线索 dmesg是从一同事处学来的,没想到今天帮我了大忙。服务器的dmesg显示,searchd进程出现了segfault: searchd[16818]: segfault at 0000000000000000 rip 000000000047242c [...]

