diff options
Diffstat (limited to 'spec/ruby/optional/capi/thread_spec.rb')
| -rw-r--r-- | spec/ruby/optional/capi/thread_spec.rb | 92 |
1 files changed, 71 insertions, 21 deletions
diff --git a/spec/ruby/optional/capi/thread_spec.rb b/spec/ruby/optional/capi/thread_spec.rb index df454d1ea8..75e0b94fdf 100644 --- a/spec/ruby/optional/capi/thread_spec.rb +++ b/spec/ruby/optional/capi/thread_spec.rb @@ -50,7 +50,7 @@ describe "C-API Thread function" do end it "returns nil if the value has not been set" do - @t.rb_thread_local_aref(Thread.current, :thread_capi_specs_undefined).should be_nil + @t.rb_thread_local_aref(Thread.current, :thread_capi_specs_undefined).should == nil end end @@ -72,7 +72,7 @@ describe "C-API Thread function" do obj = Object.new proc = -> x { ScratchPad.record x } thr = @t.rb_thread_create(proc, obj) - thr.should be_kind_of(Thread) + thr.should.is_a?(Thread) thr.join ScratchPad.recorded.should == obj end @@ -83,32 +83,42 @@ describe "C-API Thread function" do raise "my error" } thr = @t.rb_thread_create(prc, nil) - thr.should be_kind_of(Thread) + thr.should.is_a?(Thread) -> { thr.join - }.should raise_error(RuntimeError, "my error") + }.should.raise(RuntimeError, "my error") end it "sets the thread's group" do thr = @t.rb_thread_create(-> x { }, nil) begin thread_group = thr.group - thread_group.should be_an_instance_of(ThreadGroup) + thread_group.should.instance_of?(ThreadGroup) ensure thr.join end end end + describe "ruby_native_thread_p" do + it "returns non-zero for a ruby thread" do + @t.ruby_native_thread_p.should == true + end + + it "returns zero for a non ruby thread" do + @t.ruby_native_thread_p_new_thread.should == false + end + end + describe "rb_thread_call_without_gvl" do - it "runs a C function with the global lock unlocked" do + it "runs a C function with the global lock unlocked and can be woken by Thread#wakeup" do thr = Thread.new do @t.rb_thread_call_without_gvl end # Wait until it's blocking... - Thread.pass while thr.status and thr.status != "sleep" + Thread.pass until thr.stop? # The thread status is set to sleep by rb_thread_call_without_gvl(), # but the thread might not be in the blocking read(2) yet, so wait a bit. @@ -118,27 +128,67 @@ describe "C-API Thread function" do thr.wakeup # Make sure it stopped and we got a proper value - thr.value.should be_true + thr.value.should == true end - guard -> { platform_is :mingw and ruby_version_is ""..."2.7" } do - it "runs a C function with the global lock unlocked and unlocks IO with the generic RUBY_UBF_IO" do - thr = Thread.new do - @t.rb_thread_call_without_gvl_with_ubf_io + platform_is_not :windows do + it "runs a C function with the global lock unlocked and can be woken by a signal" do + # Ruby signal handlers run on the main thread, so we need to reverse roles here and have a thread interrupt us + thr = Thread.current + thr.should == Thread.main + + going_to_block = false + interrupter = Thread.new do + # Wait until it's blocking... + Thread.pass until going_to_block and thr.stop? + + # The thread status is set to sleep by rb_thread_call_without_gvl(), + # but the thread might not be in the blocking read(2) yet, so wait a bit. + sleep 0.1 + + # Wake it up by sending a signal + done = false + prev_handler = Signal.trap(:HUP) { done = true } + begin + Process.kill :HUP, Process.pid + sleep 0.001 until done + ensure + Signal.trap(:HUP, prev_handler) + end end - # Wait until it's blocking... - Thread.pass while thr.status and thr.status != "sleep" + going_to_block = true + # Make sure it stopped and we got a proper value + @t.rb_thread_call_without_gvl.should == true - # The thread status is set to sleep by rb_thread_call_without_gvl(), - # but the thread might not be in the blocking read(2) yet, so wait a bit. - sleep 0.1 + interrupter.join + end + end - # Wake it up, causing the unblock function to be run. - thr.wakeup + it "runs a C function with the global lock unlocked and unlocks IO with the generic RUBY_UBF_IO" do + thr = Thread.new do + @t.rb_thread_call_without_gvl_with_ubf_io + end - # Make sure it stopped and we got a proper value - thr.value.should be_true + # Wait until it's blocking... + Thread.pass until thr.stop? + + # The thread status is set to sleep by rb_thread_call_without_gvl(), + # but the thread might not be in the blocking read(2) yet, so wait a bit. + sleep 0.1 + + # Wake it up, causing the unblock function to be run. + thr.wakeup + + # Make sure it stopped and we got a proper value + thr.value.should == true + end + end + + ruby_version_is "4.0" do + describe "ruby_thread_has_gvl_p" do + it "returns true if the current thread has the GVL" do + @t.ruby_thread_has_gvl_p.should == true end end end |
