YJIT: Fix deadlock in tests due to pipe capacity

Previously, when there is enough stats that the child process fills up
the pipe capacity, the child process would block, with the parent
process waiting forever as no one is reading to clear up the pipe. The
test timed out in these situations.

Use a separate thread in the parent to read from the pipe to unblock the
child in these situation. EnvUtil also does this for handling stdout and
stderr.

I had the test suite deadlock on a Linux VM.
This commit is contained in:
Alan Wu 2023-03-21 18:16:33 -04:00 committed by GitHub
parent aa54082d70
commit 08eaf7c5fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
Notes: git 2023-03-21 22:17:01 +00:00
Merged: https://github.com/ruby/ruby/pull/7578

Merged-By: XrXr

View file

@ -1336,13 +1336,24 @@ class TestYJIT < Test::Unit::TestCase
args << "--yjit-exec-mem-size=#{mem_size}" if mem_size
args << "-e" << script_shell_encode(script)
stats_r, stats_w = IO.pipe
# Separate thread so we don't deadlock when
# the child ruby blocks writing the stats to fd 3
stats = ''
stats_reader = Thread.new do
stats = stats_r.read
stats_r.close
end
out, err, status = EnvUtil.invoke_ruby(args,
'', true, true, timeout: timeout, ios: {3 => stats_w}
)
stats_w.close
stats = stats_r.read
stats_reader.join(timeout)
stats = Marshal.load(stats) if !stats.empty?
stats_r.close
[status, out, err, stats]
ensure
stats_reader&.kill
stats_reader&.join(timeout)
stats_r&.close
stats_w&.close
end
end