Skip to content

Possible bug with Ruby >= 2.7.0 and GC.compact #241

@boazsegev

Description

@boazsegev

The issue was discovered by @palkan and discussed here (anycable/simple-cable-app#6)

The new feature that helps with heap fragmentation, GC.compact moves Ruby objects in the heap, changing their pointers.

Some objects are considered immovable, such as C classes and (perhaps) their instances. Also, any object referenced by a C extension using the rb_gc_mark callback is considered immovable.

nio4r uses an Array container to store references here. This array is marked with rb_gc_mark which makes it a safe, immovable, array.

However, the Ruby GC is free to move the objects within the array to a new location (while updating the reference within the Ruby array).

Only C objects are immovable, but Ruby IO objects can be moved around since they aren't independently marked by rb_gc_mark.

This means that whenever nio4r collects a reference to it's IO data structure (i.e., here and here), it is collecting a pointer that may have been moved (or some of the data within the data structure may point to an invalid pointer that was already moved).

I understand that creating an all-object GC mark data structure can be an expensive task, but there are many possible C implementations of the Set data structure, such as the one I implemented in iodine (extracted to the facio.io C STL repo and documented here.

All the code I pointed to for iodine and facil.io is MIT licensed. You're welcome to use it.

Let me know if I can help.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions