On Sat, 2007-05-26 at 10:52 +0100, Tom Hughes wrote: > In message <[EMAIL PROTECTED]> > [EMAIL PROTECTED] (Jon Burgess) wrote: > > > When the attached code is run under valgrind I get the following error. > > > > ==13906== Invalid read of size 8 > > ==13906== at 0x6B4E13C: ruby_xml_attr_free (ruby_xml_attr.c:12) > > ==13906== by 0x3C2524A9CD: rb_gc_call_finalizer_at_exit (gc.c:1928) > > ==13906== by 0x3C2522FA92: ruby_finalize_1 (eval.c:1548) > > ==13906== by 0x3C25238BFF: ruby_cleanup (eval.c:1582) > > ==13906== by 0x3C25238D28: ruby_stop (eval.c:1619) > > ==13906== by 0x3C252444C3: ruby_run (eval.c:1640) > > ==13906== by 0x4007E2: main (main.c:48) > > ==13906== Address 0x6AE4790 is 40 bytes inside a block of size 96 free'd > > ==13906== at 0x4A055AB: free (vg_replace_malloc.c:233) > > ==13906== by 0x3C2524A737: ruby_xfree (gc.c:159) > > ==13906== by 0x3C304507AE: xmlRemoveProp (in > > /usr/lib64/libxml2.so.2.6.28) > > ==13906== by 0x6B49C3D: ruby_xml_node_property_set (ruby_xml_node.c:1892) > > ==13906== by 0x3C25235BAD: rb_call0 (eval.c:5815) > > ==13906== by 0x3C252360B7: rb_call (eval.c:6062) > > ==13906== by 0x3C2523DAB3: rb_eval (eval.c:3429) > > ==13906== by 0x3C2524442A: ruby_exec_internal (eval.c:1608) > > ==13906== by 0x3C25244474: ruby_exec (eval.c:1628) > > ==13906== by 0x3C2524449F: ruby_run (eval.c:1638) > > ==13906== by 0x4007E2: main (main.c:48) > > ==13906== > > > > I think the issue is with ruby_xml_node_property_set() calling > > xmlRemoveProp() which both removes the attribute from the node and frees > > it. I think freeing the attribute needs to be conditional on there being > > no other references. > > That is one problem, yes. > > It is worse than that though, because if the node which the > attribute is attached to is freed then the attribute will be > freed (even if there are other references to it) and there is > no easy way to find out which attributes need to be kept. > > I guess you would have to walk the entire node tree checking > the _private reference count of each attribute and unlinking > anything that is shared before freeing the node? > > It's horrible anyway... > > Tom >
I'm only just starting to get my head around the interaction between C and the ruby objects and GC. The patch below seems to be a simple fix but I'm by no means certain this fixes the more general problems. I think it works because the GC implicitly performs the reference checking for the case you mention. Jon
diff -urw ref/libxml-ruby-0.3.8.4/ext/xml/ruby_xml_node.c libxml-ruby-0.3.8.4/ext/xml/ruby_xml_node.c --- ref/libxml-ruby-0.3.8.4/ext/xml/ruby_xml_node.c 2006-12-02 10:06:35.000000000 +0000 +++ libxml-ruby-0.3.8.4/ext/xml/ruby_xml_node.c 2007-05-26 16:34:48.000000000 +0100 @@ -1889,7 +1889,7 @@ if( val == Qnil ) { attr = xmlSetProp(node->node, (xmlChar*)StringValuePtr(key), NULL); - xmlRemoveProp( attr ); + xmlUnlinkNode((xmlNodePtr) attr ); return Qnil; } else { Check_Type(val, T_STRING);
_______________________________________________ libxml-devel mailing list libxml-devel@rubyforge.org http://rubyforge.org/mailman/listinfo/libxml-devel