From: Charles Oliver Nutter Date: 2009-05-16T07:05:58+09:00 Subject: [ruby-core:23467] Re: REXML Thread Safety FWIW, most DOM implementations are not thread-safe. Weston Sewell wrote: > I've been using Ruby for several years but I just joined the list > because I ran into a problem that I'm not sure how to solve (sorry for > not lurking for the requisite eon, I've been working night and day on a > Ruby project for work). > > It appears that REXML may not be completely thread-safe. Is it intended > to be? I've run into a problem that I was able to reproduce in a test > that I'll post at the bottom. Basically, it appears that accessing > either #to_s or #value on REXML::Attribute causes a change in the state > of the instance (setting @normalized and @unnormalized to a computed > value or 'nil'). And since these are not intended to be "destructive" > calls, neither are some of the Element methods that call them (i.e. > Element#inspect). When using threads of course we are not protecting > non-destructive calls with semaphors (and actually we are using XMPP4r > so we don't have complete conrol over what gets called and how). > > Is there anyone who is familiar with this situation? > > TIA > Weston > > Test Code - exception occurs in either #to_s or #value (on my system > this always happens within 900 iterations) > ------------------------------------------------------------------------------ > common_doc = REXML::Document.new( '' ) > > def parse(doc) > foo = doc.root > foo.inspect > foo.attributes['bar'] > end > > def multiparse(doc) > 1000000.times do |iteration| > puts "Iteration #{iteration}" if(iteration == 0 || (iteration % > 100 == 0)) > parse(doc) > end > end > > threads = [] > threads << Thread.new { multiparse(common_doc) } > threads << Thread.new { multiparse(common_doc) } > threads << Thread.new { multiparse(common_doc) } > threads << Thread.new { multiparse(common_doc) } > threads << Thread.new { multiparse(common_doc) } > threads << Thread.new { multiparse(common_doc) } > > threads.each do |thread| > thread.join > end >