On Fri, 02 Jun 2006 20:31:33 +0100, Doug Bryant <[EMAIL PROTECTED]> wrote:

done -
http://rubyforge.org/tracker/index.php?func=detail&aid=4635&group_id=494&atid=1971


Thanks for that. I've been working on this today, and I think it's down to the way we handle copied nodes, especially between documents. The crash occurs when the document is freed and tries to free it's nodes, since some have already been freed (with their originating document). This whole area needs some work but for now I'd appreciate if you could try the attached patch against CVS head which will (hopefully) deal with this problem case.

Cheers,
--
Ross Bamford - [EMAIL PROTECTED]
Index: ext/xml/ruby_xml_node.c
===================================================================
RCS file: /var/cvs/libxml/libxml/ext/xml/ruby_xml_node.c,v
retrieving revision 1.6
diff -u -r1.6 ruby_xml_node.c
--- ext/xml/ruby_xml_node.c	28 May 2006 14:06:14 -0000	1.6
+++ ext/xml/ruby_xml_node.c	3 Jun 2006 16:42:44 -0000
@@ -318,20 +318,33 @@
 VALUE
 ruby_xml_node_child_set(VALUE self, VALUE rnode) {
   ruby_xml_node *cnode, *pnode;
-  xmlNodePtr ret;
+  xmlNodePtr chld, ret;
+  ruby_xml_document *pdoc;
+  int ptr;
 
   if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
     rb_raise(rb_eTypeError, "Must pass an XML::Node object");
 
   Data_Get_Struct(self,  ruby_xml_node, pnode);
   Data_Get_Struct(rnode, ruby_xml_node, cnode);
-
-  ret = xmlAddChild(pnode->node, cnode->node);
+  
+  ptr = 1;
+  chld = cnode->node;
+    
+  // Only copy if both nodes are in documents, which are different.
+  if (pnode->xd && pnode->xd != Qnil && 
+      cnode->xd && cnode->xd != Qnil && 
+      pnode->xd != cnode->xd) {
+    Data_Get_Struct(pnode->xd, ruby_xml_document, pdoc);
+    chld = xmlDocCopyNode(cnode->node, pdoc->doc, 1);
+    ptr = 0;
+  }
+  
+  ret = xmlAddChild(pnode->node, chld);
   if (ret == NULL)
     rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
-
-  ruby_xml_node_set_ptr(rnode, 1);
-  return(ruby_xml_node_new2(cXMLNode, pnode->xd, ret));
+    
+  return(ruby_xml_node_new3(cXMLNode, pnode->xd, ret, ptr));
 }
 
 ////////////////////////////////////////////////
@@ -1237,17 +1250,23 @@
 
 VALUE
 ruby_xml_node_new2(VALUE class, VALUE xd, xmlNodePtr node) {
+  return ruby_xml_node_new3(class, xd, node, 1);
+}
+
+
+VALUE
+ruby_xml_node_new3(VALUE class, VALUE xd, xmlNodePtr node, int ptr) {
   ruby_xml_node *rxn;
 
   rxn = ALLOC(ruby_xml_node);
-  rxn->is_ptr = 1;
+  rxn->is_ptr = ptr;
   rxn->node = node;
   if (NIL_P(xd))
     rxn->xd = Qnil;
   else
     rxn->xd = xd;
   return(Data_Wrap_Struct(class, ruby_xml_node_mark,
-			  ruby_xml_node_free, rxn));
+                         ruby_xml_node_free, rxn));
 }
 
 
Index: ext/xml/ruby_xml_node.h
===================================================================
RCS file: /var/cvs/libxml/libxml/ext/xml/ruby_xml_node.h,v
retrieving revision 1.1
diff -u -r1.1 ruby_xml_node.h
--- ext/xml/ruby_xml_node.h	21 Feb 2006 20:40:16 -0000	1.1
+++ ext/xml/ruby_xml_node.h	3 Jun 2006 16:42:44 -0000
@@ -21,6 +21,7 @@
 VALUE ruby_xml_node_child_set(VALUE self, VALUE obj);
 VALUE ruby_xml_node_new(VALUE class, xmlNodePtr node);
 VALUE ruby_xml_node_new2(VALUE class, VALUE xd, xmlNodePtr node);
+VALUE ruby_xml_node_new3(VALUE class, VALUE xd, xmlNodePtr node, int ptr);
 VALUE ruby_xml_node_name_get(VALUE self);
 VALUE ruby_xml_node_property_get(VALUE self, VALUE key);
 VALUE ruby_xml_node_property_set(VALUE self, VALUE key, VALUE val);
_______________________________________________
libxml-devel mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/libxml-devel

Reply via email to