My linux Ruby application is using Ferret 0.11.4. I created my own
class IndexSearcher to contain
the Searcher of multiple directories. If I do not have the
searcher.close called, the end of
runner/console or runner/server will pop out with system error:
*** glibc detected *** irb: double free or corruption (fasttop):
0x0a51d6c0 ***
======= Backtrace: =========
/lib/libc.so.6[0x638ac1]
/lib/libc.so.6(cfree+0x90)[0x63c0f0]
/usr/lib/ruby/gems/gems/ferret-0.11.4/lib/ferret_ext.so[0x247d75]
/usr/lib/ruby/gems/gems/ferret-0.11.4/lib/ferret_ext.so[0x219745]
/usr/lib/libruby.so.1.8(rb_gc_call_finalizer_at_exit+0xa7)[0xc3e237]
/usr/lib/libruby.so.1.8[0xc239e7]
/usr/lib/libruby.so.1.8(ruby_cleanup+0x100)[0xc2c280]
/usr/lib/libruby.so.1.8(ruby_stop+0x1d)[0xc2c3ad]
/usr/lib/libruby.so.1.8[0xc372c1]
irb[0x804868d]
/lib/libc.so.6(__libc_start_main+0xe0)[0x5e5390]
irb[0x8048581]
Here is the code of my class. Any sign of what is wrong with the memory
handling?
class IndexSearcher
attr_accessor :searcher, :sub_searchers, :object_type
@param paths [Array of String] full local paths
def initialize( object_type, paths )
# Would’ve used this way since it’s simpler and said by author to be
faster; but invalid paths
will break this entirely
# self.searcher =
Ferret::Search::Searcher.new(Ferret::Index::IndexReader.new(paths) )
self.sub_searchers = []
paths.each do |cur_path|
begin
sub_s = Ferret::Search::Searcher.new(cur_path )
self.sub_searchers << sub_s if sub_s
rescue Exception => index_e
puts "** IndexSearcher.new: #{index_e.message}"
end
end
if self.sub_searchers.size > 0
self.searcher =
Ferret::Search::MultiSearcher.new(self.sub_searchers)
else
self.searcher = (Ferret::I.new).searcher
end
self.object_type = object_type
end
This doc/[] has a different to Index method: argument only wants
doc_id [Integer]
def doc(doc_id)
return self.searcher[doc_id]
rescue Exception => e
puts “** IndexSearcher(#{object_type}).doc #{doc_id}\n” <<
e.backtrace.join("\n")
return nil
end
alias :[] :doc
#############################
Querying methods
def process_query(query)
query.is_a?(Ferret::Search::Query) ? query :
SearchIndex::QUERY_PARSER.parse(query)
end
def search(query, options = {})
query_obj = process_query(query)
self.searcher.search( query_obj, options )
end
def search_each (query, options = {})
query_obj = process_query(query)
self.searcher.search_each( query_obj, options )
end
def explain (query, doc)
query_obj = process_query(query)
self.searcher.explain( query_obj, doc )
end
Segmentation Fault when index_searcher.highlight
def highlight (query, doc_id, options = {})
query_obj = process_query(query)
doc = self.searcher[doc_id]
field_value = doc[options[:field] ]
field_index = Ferret::I.new(:analyzer =>
SearchIndex::STEMMING_ANALYZER)
field_index << {:keywords => field_value}
fvh = field_index.highlight(query, 0, options.merge({ :field =>
:keywords }) )
return fvh
rescue Exception => e
puts “** IndexSearch.highlight(’#{query}’): #{e.message}” # <<
e.backtrace.join("\n")
return field_value
end
def doc_freq(field, term)
self.searcher.doc_freq(field, term)
end
#############################
Self Util methods
def reader
self.searcher.reader
end
def size
if reader
total_size = reader.num_docs
else
total_size = 0
self.sub_searchers.each do |sub_searcher|
total_size += sub_searcher.reader.num_docs if
sub_searcher.reader
end
return total_size
end
end
alias :num_docs :size
def close
self.searcher.close
end
end