ext/stackprof/stackprof.c in stackprof-0.2.16 vs ext/stackprof/stackprof.c in stackprof-0.2.17

- old
+ new

@@ -20,10 +20,18 @@ #define FAKE_FRAME_GC INT2FIX(0) #define FAKE_FRAME_MARK INT2FIX(1) #define FAKE_FRAME_SWEEP INT2FIX(2) +/* + * As of Ruby 3.0, it should be safe to read stack frames at any time + * See https://github.com/ruby/ruby/commit/0e276dc458f94d9d79a0f7c7669bde84abe80f21 + */ +#if RUBY_API_VERSION_MAJOR < 3 + #define USE_POSTPONED_JOB +#endif + static const char *fake_frame_cstrs[] = { "(garbage collection)", "(marking)", "(sweeping)", }; @@ -594,46 +602,50 @@ } static void stackprof_gc_job_handler(void *data) { - static int in_signal_handler = 0; - if (in_signal_handler) return; if (!_stackprof.running) return; - in_signal_handler++; stackprof_record_gc_samples(); - in_signal_handler--; } static void stackprof_job_handler(void *data) { - static int in_signal_handler = 0; - if (in_signal_handler) return; if (!_stackprof.running) return; - in_signal_handler++; stackprof_record_sample(); - in_signal_handler--; } static void stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext) { + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + _stackprof.overall_signals++; + + if (!_stackprof.running) return; + if (!ruby_native_thread_p()) return; + if (pthread_mutex_trylock(&lock)) return; + if (!_stackprof.ignore_gc && rb_during_gc()) { VALUE mode = rb_gc_latest_gc_info(sym_state); if (mode == sym_marking) { _stackprof.unrecorded_gc_marking_samples++; } else if (mode == sym_sweeping) { _stackprof.unrecorded_gc_sweeping_samples++; } _stackprof.unrecorded_gc_samples++; rb_postponed_job_register_one(0, stackprof_gc_job_handler, (void*)0); } else { +#ifdef USE_POSTPONED_JOB rb_postponed_job_register_one(0, stackprof_job_handler, (void*)0); +#else + stackprof_job_handler(0); +#endif } + pthread_mutex_unlock(&lock); } static void stackprof_newobj_handler(VALUE tpval, void *data) {