summaryrefslogtreecommitdiff
path: root/test/-ext-
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2022-07-07 15:20:35 +0200
committerJean Boussier <jean.boussier@gmail.com>2022-07-07 17:49:00 +0200
commit587d2d199b3f783d03266d42d066949f8a4824d3 (patch)
tree6977cca9dc954a2fa4a87dc1b7f1f0aa5bc8786b /test/-ext-
parent61c7ae4d27d44b19b39fa240cf7edda2eeefc92d (diff)
downloadruby-587d2d199b3f783d03266d42d066949f8a4824d3.tar.gz
thread_pthread.c: call SUSPENDED event when entering native_sleep
[Bug #18900] Thread#join and a few other codepaths are using native sleep as a way to suspend the current thread. So we should call the relevant hook when this happen, otherwise some thread may transition directly from `RESUMED` to `READY`.
Diffstat (limited to 'test/-ext-')
-rw-r--r--test/-ext-/thread/test_instrumentation_api.rb102
1 files changed, 54 insertions, 48 deletions
diff --git a/test/-ext-/thread/test_instrumentation_api.rb b/test/-ext-/thread/test_instrumentation_api.rb
index fe91c942c7..78e499c473 100644
--- a/test/-ext-/thread/test_instrumentation_api.rb
+++ b/test/-ext-/thread/test_instrumentation_api.rb
@@ -3,76 +3,82 @@ require 'envutil'
class TestThreadInstrumentation < Test::Unit::TestCase
def setup
- pend("TODO: No windows support yet") if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
- end
-
- THREADS_COUNT = 3
+ pend("No windows support") if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
- def test_thread_instrumentation
require '-test-/thread/instrumentation'
Bug::ThreadInstrumentation.reset_counters
Bug::ThreadInstrumentation::register_callback
+ end
- begin
- threads = threaded_cpu_work
- assert_equal [false] * THREADS_COUNT, threads.map(&:status)
- counters = Bug::ThreadInstrumentation.counters
- counters.each do |c|
- assert_predicate c, :nonzero?, "Call counters: #{counters.inspect}"
- end
-
- assert_equal THREADS_COUNT, counters.first
- assert_in_delta THREADS_COUNT, counters.last, 1 # It's possible that a thread didn't execute its EXIT hook yet.
- ensure
- Bug::ThreadInstrumentation::unregister_callback
+ def teardown
+ return if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+ Bug::ThreadInstrumentation::unregister_callback
+ end
+
+ THREADS_COUNT = 3
+
+ def test_thread_instrumentation
+ threads = threaded_cpu_work
+ assert_equal [false] * THREADS_COUNT, threads.map(&:status)
+ counters = Bug::ThreadInstrumentation.counters
+ counters.each do |c|
+ assert_predicate c, :nonzero?, "Call counters: #{counters.inspect}"
end
+
+ assert_equal THREADS_COUNT, counters.first
+ assert_in_delta THREADS_COUNT, counters.last, 1 # It's possible that a thread didn't execute its EXIT hook yet.
+ end
+
+ def test_join_counters # Bug #18900
+ thr = Thread.new { fib(30) }
+ Bug::ThreadInstrumentation.reset_counters
+ thr.join
+ assert_equal [1, 1, 1], Bug::ThreadInstrumentation.local_counters
end
def test_thread_instrumentation_fork_safe
skip "No fork()" unless Process.respond_to?(:fork)
- require '-test-/thread/instrumentation'
- Bug::ThreadInstrumentation::register_callback
-
read_pipe, write_pipe = IO.pipe
- begin
- pid = fork do
- Bug::ThreadInstrumentation.reset_counters
- threads = threaded_cpu_work
- write_pipe.write(Marshal.dump(threads.map(&:status)))
- write_pipe.write(Marshal.dump(Bug::ThreadInstrumentation.counters))
- write_pipe.close
- exit!(0)
- end
+ pid = fork do
+ Bug::ThreadInstrumentation.reset_counters
+ threads = threaded_cpu_work
+ write_pipe.write(Marshal.dump(threads.map(&:status)))
+ write_pipe.write(Marshal.dump(Bug::ThreadInstrumentation.counters))
write_pipe.close
- _, status = Process.wait2(pid)
- assert_predicate status, :success?
-
- thread_statuses = Marshal.load(read_pipe)
- assert_equal [false] * THREADS_COUNT, thread_statuses
-
- counters = Marshal.load(read_pipe)
- read_pipe.close
- counters.each do |c|
- assert_predicate c, :nonzero?, "Call counters: #{counters.inspect}"
- end
-
- assert_equal THREADS_COUNT, counters.first
- assert_in_delta THREADS_COUNT, counters.last, 1 # It's possible that a thread didn't execute its EXIT hook yet.
- ensure
- Bug::ThreadInstrumentation::unregister_callback
+ exit!(0)
end
+ write_pipe.close
+ _, status = Process.wait2(pid)
+ assert_predicate status, :success?
+
+ thread_statuses = Marshal.load(read_pipe)
+ assert_equal [false] * THREADS_COUNT, thread_statuses
+
+ counters = Marshal.load(read_pipe)
+ read_pipe.close
+ counters.each do |c|
+ assert_predicate c, :nonzero?, "Call counters: #{counters.inspect}"
+ end
+
+ assert_equal THREADS_COUNT, counters.first
+ assert_in_delta THREADS_COUNT, counters.last, 1 # It's possible that a thread didn't execute its EXIT hook yet.
end
def test_thread_instrumentation_unregister
- require '-test-/thread/instrumentation'
+ Bug::ThreadInstrumentation::unregister_callback
assert Bug::ThreadInstrumentation::register_and_unregister_callbacks
end
private
- def threaded_cpu_work
- THREADS_COUNT.times.map { Thread.new { 100.times { |i| i + i } } }.each(&:join)
+ def fib(n = 20)
+ return n if n <= 1
+ fib(n-1) + fib(n-2)
+ end
+
+ def threaded_cpu_work(size = 20)
+ THREADS_COUNT.times.map { Thread.new { fib(size) } }.each(&:join)
end
end