diff --git a/ext/ffi_c/Function.c b/ext/ffi_c/Function.c index 305f8b180..f68d1320f 100644 --- a/ext/ffi_c/Function.c +++ b/ext/ffi_c/Function.c @@ -310,6 +310,8 @@ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc) #if defined(DEFER_ASYNC_CALLBACK) if (async_cb_thread == Qnil) { async_cb_thread = rb_thread_create(async_cb_event, NULL); + /* Name thread, for better debugging */ + rb_funcall(async_cb_thread, rb_intern("name="), 1, rb_str_new2("FFI::Function Callback Dispatcher")); } #endif @@ -525,7 +527,9 @@ async_cb_event(void* unused) rb_thread_call_without_gvl(async_cb_wait, &w, async_cb_stop, &w); if (w.cb != NULL) { /* Start up a new ruby thread to run the ruby callback */ - rb_thread_create(async_cb_call, w.cb); + VALUE new_thread = rb_thread_create(async_cb_call, w.cb); + /* Name thread, for better debugging */ + rb_funcall(new_thread, rb_intern("name="), 1, rb_str_new2("FFI::Function Callback Runner")); } } diff --git a/spec/ffi/async_callback_spec.rb b/spec/ffi/async_callback_spec.rb index 3d24369f5..aab54e052 100644 --- a/spec/ffi/async_callback_spec.rb +++ b/spec/ffi/async_callback_spec.rb @@ -34,4 +34,15 @@ module LibTest expect(called).to be true expect(v).to eq(0x7fffffff) end + + it "sets the name of the thread that runs the callback" do + skip "not yet supported on TruffleRuby" if RUBY_ENGINE == "truffleruby" + skip "not yet supported on JRuby" if RUBY_ENGINE == "jruby" + + callback_runner_thread = nil + + LibTest.testAsyncCallback(proc { callback_runner_thread = Thread.current }, 0) + + expect(callback_runner_thread.name).to eq("FFI::Function Callback Runner") + end end diff --git a/spec/ffi/function_spec.rb b/spec/ffi/function_spec.rb index dd4d2eaaf..a7d6dc718 100644 --- a/spec/ffi/function_spec.rb +++ b/spec/ffi/function_spec.rb @@ -21,6 +21,15 @@ module LibTest expect(fn.call).to eql 5 end + context 'when called with a block' do + it 'creates a thread for dispatching callbacks and sets its name' do + skip 'this is MRI-specific' if RUBY_ENGINE == 'truffleruby' || RUBY_ENGINE == 'jruby' + FFI::Function.new(:int, []) { 5 } # Trigger initialization + + expect(Thread.list.map(&:name)).to include('FFI::Function Callback Dispatcher') + end + end + it 'raises an error when passing a wrong signature' do expect { FFI::Function.new([], :int).new { } }.to raise_error TypeError end