diff --git a/ext/stackprof/extconf.rb b/ext/stackprof/extconf.rb index 742ff463..c5386ef0 100644 --- a/ext/stackprof/extconf.rb +++ b/ext/stackprof/extconf.rb @@ -5,7 +5,8 @@ return end -if have_func('rb_postponed_job_register_one') && +if (have_func('rb_postponed_job_preregister') || + have_func('rb_postponed_job_register_one')) && have_func('rb_profile_frames') && have_func('rb_tracepoint_new') && have_const('RUBY_INTERNAL_EVENT_NEWOBJ') diff --git a/ext/stackprof/stackprof.c b/ext/stackprof/stackprof.c index 36033812..5241b80d 100644 --- a/ext/stackprof/stackprof.c +++ b/ext/stackprof/stackprof.c @@ -26,6 +26,16 @@ #define FAKE_FRAME_MARK INT2FIX(1) #define FAKE_FRAME_SWEEP INT2FIX(2) +#ifdef HAVE_RB_POSTPONED_JOB_PREREGISTER +static rb_postponed_job_handle_t job_record_gc, job_sample_and_record, job_record_buffer; + +# define preregister_job(job) (job = rb_postponed_job_preregister(0, stackprof_##job, (void*)0)) +# define trigger_job(job) rb_postponed_job_trigger(job) +#else +# define preregister_job(job) ((void*)0) +# define trigger_job(job) rb_postponed_job_register_one(0, stackprof_##job, (void*)0) +#endif + static const char *fake_frame_cstrs[] = { "(garbage collection)", "(marking)", @@ -225,7 +235,7 @@ stackprof_start(int argc, VALUE *argv, VALUE self) sigaction(mode == sym_wall ? SIGALRM : SIGPROF, &sa, NULL); timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = NUM2LONG(interval); + timer.it_interval.tv_usec = NUM2UINT(interval); timer.it_value = timer.it_interval; setitimer(mode == sym_wall ? ITIMER_REAL : ITIMER_PROF, &timer, 0); } else if (mode == sym_custom) { @@ -813,16 +823,16 @@ stackprof_signal_handler(int sig, siginfo_t *sinfo, void *ucontext) capture_timestamp(&_stackprof.gc_start_timestamp); } _stackprof.unrecorded_gc_samples++; - rb_postponed_job_register_one(0, stackprof_job_record_gc, (void*)0); + trigger_job(job_record_gc); } else { if (stackprof_use_postponed_job) { - rb_postponed_job_register_one(0, stackprof_job_sample_and_record, (void*)0); + trigger_job(job_sample_and_record); } else { // Buffer a sample immediately, if an existing sample exists this will // return immediately stackprof_buffer_sample(); // Enqueue a job to record the sample - rb_postponed_job_register_one(0, stackprof_job_record_buffer, (void*)0); + trigger_job(job_record_buffer); } } pthread_mutex_unlock(&lock); @@ -899,7 +909,7 @@ stackprof_atfork_parent(void) if (STACKPROF_RUNNING()) { if (_stackprof.mode == sym_wall || _stackprof.mode == sym_cpu) { timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = NUM2LONG(_stackprof.interval); + timer.it_interval.tv_usec = NUM2UINT(_stackprof.interval); timer.it_value = timer.it_interval; setitimer(_stackprof.mode == sym_wall ? ITIMER_REAL : ITIMER_PROF, &timer, 0); } @@ -1010,5 +1020,9 @@ Init_stackprof(void) rb_define_singleton_method(rb_mStackProf, "sample", stackprof_sample, 0); rb_define_singleton_method(rb_mStackProf, "use_postponed_job!", stackprof_use_postponed_job_l, 0); + preregister_job(job_record_gc); + preregister_job(job_sample_and_record); + preregister_job(job_record_buffer); + pthread_atfork(stackprof_atfork_prepare, stackprof_atfork_parent, stackprof_atfork_child); } diff --git a/test/test_stackprof.rb b/test/test_stackprof.rb index b979e344..7dfbec45 100644 --- a/test/test_stackprof.rb +++ b/test/test_stackprof.rb @@ -51,9 +51,16 @@ def test_object_allocation frame = profile[:frames].values.first assert_includes frame[:name], "StackProfTest#test_object_allocation" - assert_equal 2, frame[:samples] + if RUBY_VERSION >= '4' + assert_equal 4, frame[:samples] + else + assert_equal 2, frame[:samples] + end assert_includes [profile_base_line - 2, profile_base_line], frame[:line] - if RUBY_VERSION >= '3' + if RUBY_VERSION >= '4' + assert_equal [2, 2], frame[:lines][profile_base_line+1] + assert_equal [2, 2], frame[:lines][profile_base_line+2] + elsif RUBY_VERSION >= '3' assert_equal [2, 1], frame[:lines][profile_base_line+1] assert_equal [2, 1], frame[:lines][profile_base_line+2] else @@ -151,7 +158,7 @@ def test_raw assert_equal 10, raw_lines[-1] # seen 10 times offset = RUBY_VERSION >= '3' ? -3 : -2 - assert_equal 140, raw_lines[offset] # sample caller is on 140 + assert_equal 147, raw_lines[offset] # sample caller is on 140 assert_includes profile[:frames][raw[offset]][:name], 'StackProfTest#test_raw' assert_equal 10, profile[:raw_sample_timestamps].size