From fe6974a8fcca42f4f83171097a3bc29fbe0f2f67 Mon Sep 17 00:00:00 2001 From: k0kubun Date: Sun, 18 Nov 2018 08:25:48 +0000 Subject: mjit_worker.c: support MJIT in forked Ruby process by launching MJIT worker thread in child Ruby process. See the comment before `mjit_child_after_fork` for details. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65785 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/ruby/test_jit.rb | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) (limited to 'test/ruby/test_jit.rb') diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb index 451ed91a56..b25a9b15a2 100644 --- a/test/ruby/test_jit.rb +++ b/test/ruby/test_jit.rb @@ -567,7 +567,7 @@ class TestJIT < Test::Unit::TestCase assert_match(/^Successful MJIT finish$/, err) end - def test_unload_units + def test_unload_units_and_compaction Dir.mktmpdir("jit_test_unload_units_") do |dir| # MIN_CACHE_SIZE is 10 out, err = eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~'end;'}", verbose: 1, min_calls: 1, max_cache: 10) @@ -582,6 +582,12 @@ class TestJIT < Test::Unit::TestCase EOS i += 1 end + + if defined?(fork) + # test the child does not try to delete files which are deleted by parent, + # and test possible deadlock on fork during MJIT unload and JIT compaction on child + Process.waitpid(Process.fork {}) + end end; debug_info = "stdout:\n```\n#{out}\n```\n\nstderr:\n```\n#{err}```\n" @@ -598,7 +604,7 @@ class TestJIT < Test::Unit::TestCase # On --jit-wait, when the number of JIT-ed code reaches --jit-max-cache, # it should trigger compaction. unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet - assert_equal(2, compactions.size, debug_info) + assert_equal(3, compactions.size, debug_info) end if appveyor_mswin? @@ -838,6 +844,36 @@ class TestJIT < Test::Unit::TestCase assert_equal("-e:8:in `a'\n", lines[1]) end + def test_fork_with_mjit_worker_thread + Dir.mktmpdir("jit_test_fork_with_mjit_worker_thread_") do |dir| + # min_calls: 2 to skip fork block + out, err = eval_with_jit({ "TMPDIR" => dir }, "#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 2, verbose: 1) + begin; + def before_fork; end + def after_fork; end + + before_fork; before_fork # the child should not delete this .o file + pid = Process.fork do # this child should not delete shared .pch file + after_fork; after_fork # this child does not share JIT-ed after_fork with parent + end + after_fork; after_fork # this parent does not share JIT-ed after_fork with child + + Process.waitpid(pid) + end; + success_count = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size + assert_equal(3, success_count) + + # assert no remove error + lines = err.lines + assert_match(/^Successful MJIT finish$/, lines[3]) + assert_match(/^Successful MJIT finish$/, lines[4]) + + # ensure objects are deleted + debug_info = "stdout:\n```\n#{out}\n```\n\nstderr:\n```\n#{err}```\n" + assert_send([Dir, :empty?, dir], debug_info) + end + end if defined?(fork) + private def appveyor_mswin? -- cgit v1.2.3