Skip to content

Commit

Permalink
Merge pull request #200 from ianks/ruby-signal-safety
Browse files Browse the repository at this point in the history
Ensure VM is running in signal handler
  • Loading branch information
tenderlove authored Mar 20, 2023
2 parents 52d1df6 + 455d76a commit eb1db9f
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions ext/stackprof/stackprof.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <ruby/st.h>
#include <ruby/io.h>
#include <ruby/intern.h>
#include <ruby/vm.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>
Expand All @@ -32,6 +33,7 @@ static const char *fake_frame_cstrs[] = {
};

static int stackprof_use_postponed_job = 1;
static int ruby_vm_running = 0;

#define TOTAL_FAKE_FRAMES (sizeof(fake_frame_cstrs) / sizeof(char *))

Expand Down Expand Up @@ -725,6 +727,11 @@ stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext)

if (!_stackprof.running) return;

// There's a possibility that the signal handler is invoked *after* the Ruby
// VM has been shut down (e.g. after ruby_cleanup(0)). In this case, things
// that rely on global VM state (e.g. rb_during_gc) will segfault.
if (!ruby_vm_running) return;

if (_stackprof.mode == sym_wall) {
// In "wall" mode, the SIGALRM signal will arrive at an arbitrary thread.
// In order to provide more useful results, especially under threaded web
Expand Down Expand Up @@ -845,6 +852,12 @@ stackprof_use_postponed_job_l(VALUE self)
return Qnil;
}

static void
stackprof_at_exit(ruby_vm_t* vm)
{
ruby_vm_running = 0;
}

void
Init_stackprof(void)
{
Expand All @@ -855,6 +868,9 @@ Init_stackprof(void)
*/
stackprof_use_postponed_job = RUBY_API_VERSION_MAJOR < 3;

ruby_vm_running = 1;
ruby_vm_at_exit(stackprof_at_exit);

#define S(name) sym_##name = ID2SYM(rb_intern(#name));
S(object);
S(custom);
Expand Down

0 comments on commit eb1db9f

Please sign in to comment.