You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
gc: Do not finish lazy sweeps when freeing the object space
When freeing the object space from `ruby_vm_destruct`, we were performing a `gc_rest_sweep` to wrap up any potentially undergoing lazy sweeps. This operation is extremely dangerous because it is performed without a GVL (which has been removed previously in `ruby_vm_destruct`) and without a main thread to operate with (which has been cleared previously when freeing the main VM thread in `ruby_vm_destruct`). Since finishing a lazy sweep on the heap can cause objects to be deallocated, if the free function of any of these objects uses threading information, it will segfault. The builtin `Fiber` object (cont.c), for instance, accesses current thread information with `GET_THREAD()` when being freed, and can potentially segfault. Any user defined T_DATA with a free callback can also trigger segfaults, and likewise for any object in Rubyland with a finalizer. Because of the way that the MRI teardown process functions, the only way that a lazy sweep can be underway when freeing the object space is if it was triggered when calling the on-exit finalizers (`rb_gc_call_finalizer_at_exit`). Before calling all the object finalizers, `rb_objspace_call_finalizer` finishes any current lazy sweeps. However, since the process of calling finalizers can allocate more objects on the Ruby heap, it is possible for a call to `newobj` to start another lazy sweep phase. Hence, instead of finishing the lazy sweep when freeing the object space, we attempt to finish it right after all the finalizers have been called. This way, we can assert that no lazy sweeps and no object deallocation will be performed after the main thread and the GVL have been cleared.
0 commit comments