This might be one of those "everything wants to run after everything else" situations, but...
ruby_vm_run_at_exit_hooks is called before rb_objspace_free_objects during shutdown; that means extension dfree methods might be called after the atexit hooks they registered. My sense is that normally extensions will want that the other way around? If a C library offers a kind of global shutdown function, it's normally invalid to call any of the library's functions after that. E.g. for libxml which was mentioned in the previous ticket: https://gnome.pages.gitlab.gnome.org/libxml2/devhelp/libxml2-parser.html
xmlCleanupParser ()
void xmlCleanupParser (void)
This function name is somewhat misleading. It does not clean up parser state, it cleans up memory allocated by the library itself. It is a cleanup function for the XML library. It tries to reclaim all related global memory allocated for the library processing. It doesn't deallocate any document related memory. One should call xmlCleanupParser() only when the process has finished using the library and all XML/HTML documents built with it. See also xmlInitParser() which has the opposite function of preparing the library for operations. WARNING: if your application is multithreaded or has plugin support calling this may crash the application if another thread or a plugin is still using libxml2. It's sometimes very hard to guess if libxml2 is in use in the application, some libraries or plugins may use it without notice. In case of doubt abstain from calling this function or do it just before calling exit() to avoid leak reports from valgrind !
On the other hand, a C extension might want to do something with its Ruby objects before they get freed by rb_objspace_free_objects.....
Do we actually need two sets of atexit hooks here?