summaryrefslogtreecommitdiff
path: root/test/ruby/test_thread.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_thread.rb')
-rw-r--r--test/ruby/test_thread.rb74
1 files changed, 68 insertions, 6 deletions
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index ba2c5b8e7c..da14c429e6 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -3,6 +3,7 @@
require 'test/unit'
require "rbconfig/sizeof"
require "timeout"
+require "fiddle"
class TestThread < Test::Unit::TestCase
class Thread < ::Thread
@@ -29,13 +30,19 @@ class TestThread < Test::Unit::TestCase
end
def test_inspect
+ m = Thread::Mutex.new
+ m.lock
line = __LINE__+1
- th = Module.new {break module_eval("class C\u{30b9 30ec 30c3 30c9} < Thread; self; end")}.start{}
+ th = Module.new {break module_eval("class C\u{30b9 30ec 30c3 30c9} < Thread; self; end")}.start do
+ m.synchronize {}
+ end
+ Thread.pass until th.stop?
s = th.inspect
assert_include(s, "::C\u{30b9 30ec 30c3 30c9}:")
assert_include(s, " #{__FILE__}:#{line} ")
assert_equal(s, th.to_s)
ensure
+ m.unlock
th.join
end
@@ -317,7 +324,7 @@ class TestThread < Test::Unit::TestCase
s += 1
end
Thread.pass until t.stop?
- sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait
+ sleep 1 if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait
assert_equal(1, s)
t.wakeup
Thread.pass while t.alive?
@@ -389,7 +396,7 @@ class TestThread < Test::Unit::TestCase
end
INPUT
- assert_in_out_err(%w(--disable-gems -d), <<-INPUT, %w(false 2), %r".+")
+ assert_in_out_err(%w(-d), <<-INPUT, %w(false 2), %r".+")
p Thread.abort_on_exception
begin
t = Thread.new { raise }
@@ -966,6 +973,8 @@ _eom
end
def test_thread_timer_and_interrupt
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
bug5757 = '[ruby-dev:44985]'
pid = nil
cmd = 'Signal.trap(:INT, "DEFAULT"); pipe=IO.pipe; Thread.start {Thread.pass until Thread.main.stop?; puts; STDOUT.flush}; pipe[0].read'
@@ -1244,6 +1253,21 @@ q.pop
assert_predicate(status, :success?, bug9751)
end if Process.respond_to?(:fork)
+ def test_fork_value
+ bug18902 = "[Bug #18902]"
+ th = Thread.start { sleep 2 }
+ begin
+ pid = fork do
+ th.value
+ end
+ _, status = Process.wait2(pid)
+ assert_predicate(status, :success?, bug18902)
+ ensure
+ th.kill
+ th.join
+ end
+ end if Process.respond_to?(:fork)
+
def test_fork_while_locked
m = Thread::Mutex.new
thrs = []
@@ -1411,7 +1435,8 @@ q.pop
Thread.pass until th1.stop?
# After a thread starts (and execute `sleep`), it returns native_thread_id
- assert_instance_of Integer, th1.native_thread_id
+ native_tid = th1.native_thread_id
+ assert_instance_of Integer, native_tid if native_tid # it can be nil
th1.wakeup
Thread.pass while th1.alive?
@@ -1420,11 +1445,40 @@ q.pop
assert_nil th1.native_thread_id
end
+ def test_thread_native_thread_id_across_fork_on_linux
+ rtld_default = Fiddle.dlopen(nil)
+ omit "this test is only for Linux" unless rtld_default.sym_defined?('gettid')
+
+ gettid = Fiddle::Function.new(rtld_default['gettid'], [], Fiddle::TYPE_INT)
+
+ parent_thread_id = Thread.main.native_thread_id
+ real_parent_thread_id = gettid.call
+
+ assert_equal real_parent_thread_id, parent_thread_id
+
+ child_lines = nil
+ IO.popen('-') do |pipe|
+ if pipe
+ # parent
+ child_lines = pipe.read.lines
+ else
+ # child
+ puts Thread.main.native_thread_id
+ puts gettid.call
+ end
+ end
+ child_thread_id = child_lines[0].chomp.to_i
+ real_child_thread_id = child_lines[1].chomp.to_i
+
+ assert_equal real_child_thread_id, child_thread_id
+ refute_equal parent_thread_id, child_thread_id
+ end
+
def test_thread_interrupt_for_killed_thread
opts = { timeout: 5, timeout_error: nil }
- # prevent SIGABRT from slow shutdown with MJIT
- opts[:reprieve] = 3 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
+ # prevent SIGABRT from slow shutdown with RJIT
+ opts[:reprieve] = 3 if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
assert_normal_exit(<<-_end, '[Bug #8996]', **opts)
Thread.report_on_exception = false
@@ -1493,4 +1547,12 @@ q.pop
end
};
end
+
+ def test_pending_interrupt?
+ t = Thread.handle_interrupt(Exception => :never) { Thread.new { Thread.stop } }
+ t.raise(StandardError)
+ assert_equal(true, t.pending_interrupt?)
+ assert_equal(true, t.pending_interrupt?(Exception))
+ assert_equal(false, t.pending_interrupt?(ArgumentError))
+ end
end