-
Notifications
You must be signed in to change notification settings - Fork 132
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
Use more accurate profiling on Ruby 3.1 and fix async-signal-safety #172
Conversation
This is necessary for RUBY_API_VERSION_MAJOR, at least in Ruby 3.1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a couple comments, but the overall approach makes sense to me.
In 6c3f4d7 we started recording signals immediately on receiving a signal, after observing that in Ruby 3.0+ the CFP structure was safe to read. This resulted in much more accurate measurements. Unfortunately though rb_profile_frames seems to be safe to call inside a signal handler, stackprof_record_sample_for_stack is not, since it calls malloc (itself or through st_*) which is not async-signal-safe. This could potentially result in deadlocks or memory corruption depending on the malloc implementation. This commit attempts to restore the safety of the postponed job approach while keeping the accuracy of measuring immediately. Inside the signal handler we record the frames to a buffer, then enqueue a postponed job to do the actual recording.
0fa6a43
to
7a8e4ca
Compare
Quick heads up, while testing ruby/ruby#6572, I got a VM crash in stackprof:
I haven't investigated it much just yet, but I suspect ruby/ruby#6572 might break the async-signal safety assumption? |
Also note that the crash only happens in CPU mode, WALL mode still work fine. |
I would be surprised to see async-signal-safety related to the crash you saw, since that PR is also using |
Accuracy Regression
In Ruby 3.1, stackprof was building with the warning:
Because of this, stackprof wasn't using the much improved accuracy added in #150 for Ruby 3.0+. This is fixed by adding an include of
ruby/version.h
Async signal safety
Revisiting #150, I noticed that approach wasn't quite safe 😅.
Unfortunately though rb_profile_frames seems to be safe to call inside a signal handler, stackprof_record_sample_for_stack is not, since it calls malloc (itself or through st_*) which is not async-signal-safe. This could potentially result in deadlocks or memory corruption depending on the malloc implementation.
This commit attempts to restore the safety of the postponed job approach while keeping the accuracy of measuring immediately. Inside the signal handler we record the frames to a buffer, then enqueue a postponed job to do the actual recording.
I am interested in further improving this by adding a worker thread to do the processing of the buffer instead of doing it in the postponed job, however I'd like to apply this as a smaller fix first and attempt that in a future PR.