Hi.

2012/2/17 Tim Elliott <tle / holymonkey.com>:
> On Wed, Feb 15, 2012 at 4:39 PM, Eric Wong <normalperson / yhbt.net> wrote:
>> I've reproduced the original issue on both 1.9.3-p0 and p105 on
>> x86_64-linux.         
>> not appear to manifest on 1.9.2, so maybe it is a bad interaction with
>> lazy-sweep in 1.9.3
>
> I've isolated the issue to a ruby extension that has 140 lines of C
> code and shows the same (or a similar) segfault.
>
> If this is helpful, you can clone it here:
> git://github.com/ender672/minigiri.git
>
> Or view the C code here:
> https://github.com/ender672/minigiri/blob/master/minigiri.c
>
> Some things it does may seem strange, but that is because it tries to
> match what Nokogiri does.

Thanks for a your simple reproducible code.

I think it's lazy-sweep bug, so I'm going to fix it.

If a your program start Full GC (GC.strat,etc..) during lazy sweeping,
unmarked objects (dead objects) in unsweeped slots are not freed,
because we trust that FullGC will free their.
However, in the mark phase of FullGC, a dead object might be marked by a
false pointer. I think this is a bug.

In Nokogiri, as following, 'data[doc]' has dfree and 'data[node]' has
dmark.
# data[doc] is Data_Wrap_Struct(klass, 0, doc_dealloc, doc).
# data[node] is Data_Wrap_Struct(klass, mark, 0, node).

         dfree                              dmark
 data[doc] -> doc -> node   data[doc] <- node <- data[node]

If lazy sweep frees a data[doc], then we start the mark phase in
interrupt FullGC, data[node] might be marked by the above reason.
This mark raises SEGV because data[doc] and doc and node are freed.

Your patch which sets data[node] to the instance variable in data[doc]
avoids the above problem, because the object flag on a freed data[doc]
is 0, so it avoids this mark process.

Regards.

-- 
Narihiro Nakamura (nari)