-
Notifications
You must be signed in to change notification settings - Fork 5.4k
[Bug #19922] Ensure Objspace.dump_all is a consistnt heap snapshot #9353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
[Bug #19922] Ensure Objspace.dump_all is a consistnt heap snapshot #9353
Conversation
f78496e
to
7701e10
Compare
I believe "NO". I understand:
But I couldn't understand why they are needed:
|
Are there any portability problems with doing this, do you know? Can we extract the FD from the IO object, set it to blocking, and then just call |
@ko1 I did some more research into this, and I think it's less complex to add this The problem is, if we're given an IO to dump to, we don't know if that IO's file descriptor is set as blocking or nonblocking at the OS level. That means we have two options:
The problem with option 1, is that although we have a I guess the signature of what we want to add is...
or something along those lines. The problem with option 2 is that we would need to replicate the machinery about whether to use The reason I think my suggested approach in this PR is better is that it doesn't leak platform-specific stuff like FD O_NONBLOCK state, select vs poll, etc into objspace. Instead, we tell Ruby what we want to achieve ("I want this block to be the only possible code that can run in the VM until it finishes"), and then keep using all the ordinary I/O machinery just like we always would. |
Do not introduce general Thread control mechanism for the specific purpose like this. It is too much only for this purpose. |
For example, we can dump all output to a temp file with C manner (no-Ruby related). After that we can put Ruby's IO from that file. Of course we can store all dumps to the memory but I'm not sure it is feasible. |
Oh that's not a bad idea actually. Let me try that. Thanks for the suggestion. |
578cc36
to
12fdfa9
Compare
Well this almost works, except I need to exclude other Ractors still, and @ko1 would you mind if I added an exported version of that macro to (alternatively: I wonder if objspace dump should be in an extension module at all - maybe it should just be linked with directly? it requires intimate knowledge about how objects in cruby work anyway) |
objspace extension is tightly coupled with MRI internal so I suggest:
|
12fdfa9
to
247e3e2
Compare
This needs to give a consistent snapshot of the heap, but if we're writing the dump to a file object, the IO could actually cause a thread switch to occur. Currently, this can cause a crash if dump_all invocations are run concurrently. However, even if it didn't, the heap snapshot still wouldn't be consistent. We achieve this by: * Exclude other Ractors by using a wrapper around RB_VM_LOCK_ENTER * Exclude other threads by perfoming all file IO using native C blocking IO (to a tempfile), and only copying it back to Ruby once the dump is done. [Bug #19922]
rb_objspace_reachable_objects_from has it too, so I figure it's most likely required for _from_root as well.
247e3e2
to
c3a76c3
Compare
OK, I added
to Is this what you had in mind? Or did you more have in mind something like
to be added to |
@ko1 Would appreciate your opinion on ☝️ when you have time 🙏 thank you. |
This PR contains two things:
vm_sync.h
,RB_VM_LOCK_ENTER_ISOLATE
. This is designed to ensure that the locked code is the only code that can run anywhere in the VM during its scope, even if the code performs something that would normally be a blocking operation and trigger a thread switch. It does this by doing four things:dont_switch
flag to the thread, and consulting that before marking the thread as performing a "blocking operation")Objspace.dump_all
use this mechanism to ensure that no code can run while we're dumping the heap, resulting in a consistent heap snapshot, even if the heap is being dumped to an IO device.Three things I'm not sure about
RB_VM_LOCK_ENTER_ISOLATE
? Presumably you don't want GC to trigger during heap dumping?Objspace.dump_all
becomes invisible to profilers.https://bugs.ruby-lang.org/issues/19922