Please sign in to comment.
Clean all occurrences of _private on GC when libxml-ruby is loaded.
libxml-ruby uses the global libxml2 callback xmlDeregisterNodeDefault. This callback looks in the _private field for every deleted libxml2 node. If the _private field is set, it is treated as a Ruby VALUE ptr. The callback NULLs the Ruby object's data pointer and mark & free fn pointers. When Nokogiri wraps a libxml2 document it puts a nokogiriTuple ptr in the _private field. We can't let the libxml-ruby callback be invoked on a libxml2 document before NULLing the document _private field. When Nokogiri wraps other libxml2 nodes it puts VALUE ptrs in the _private field. This makes the libxml-ruby callback generally safe for these node types. There is a caveat - it is unsafe to access VALUE ptrs during GC sweep. This commit tests whether the xmlDeregisterNodeDefault callback is set during document cleanup. If set, we traverse the document and clean up all _private fields. The previous solution was to unset xmlDeregisterNodeDefault callback. However, this doesn't work in multithreaded environments.
- Loading branch information...