Closed boazsegev closed 3 years ago
Do you have time to make a PR? I will accept it. My time right now is very limited.
I think it might take me a week or two, since:
I've never used nioi4r
and I don't know the API that well.
I'm a 42 year old student (again), dealing with both normal life deadlines and the end of my online semester (final projects) 😅
But I can play around and see what I can do... if the timeframe is fine.
This fix has been merged and will be released shortly.
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 withrb_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.