Brian Gan
2008-Mar-05 17:06 UTC
[Ferret-talk] Index Searcher Causes GC Memory Error: "irb: double free or corruption"
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