-
-
Notifications
You must be signed in to change notification settings - Fork 91
Possible bug with Ruby >= 2.7.0 and GC.compact #241
Description
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.