Skip to content

Commit eead039

Browse files
Merge pull request rails#45667 from sambostock/fix-fd-in-isolation
Ensure pipe is closed after test run
2 parents b065d5a + 1bd5220 commit eead039

File tree

2 files changed

+41
-27
lines changed

2 files changed

+41
-27
lines changed

activesupport/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
* Ensure `ActiveSupport::Testing::Isolation::Forking` closes pipes
2+
3+
Previously, `Forking.run_in_isolation` opened two ends of a pipe. The fork
4+
process closed the read end, wrote to it, and then terminated (which
5+
presumably closed the file descriptors on its end). The parent process
6+
closed the write end, read from it, and returned, never closing the read
7+
end.
8+
9+
This resulted in an accumulation of open file descriptors, which could
10+
cause errors if the limit is reached.
11+
12+
*Sam Bostock*
13+
114
* Fix `Time#change` and `Time#advance` for times around the end of Daylight
215
Saving Time.
316

activesupport/lib/active_support/testing/isolation.rb

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,38 +25,39 @@ def run
2525

2626
module Forking
2727
def run_in_isolation(&blk)
28-
read, write = IO.pipe
29-
read.binmode
30-
write.binmode
28+
IO.pipe do |read, write|
29+
read.binmode
30+
write.binmode
3131

32-
pid = fork do
33-
read.close
34-
yield
35-
begin
36-
if error?
37-
failures.map! { |e|
38-
begin
39-
Marshal.dump e
40-
e
41-
rescue TypeError
42-
ex = Exception.new e.message
43-
ex.set_backtrace e.backtrace
44-
Minitest::UnexpectedError.new ex
45-
end
46-
}
32+
pid = fork do
33+
read.close
34+
yield
35+
begin
36+
if error?
37+
failures.map! { |e|
38+
begin
39+
Marshal.dump e
40+
e
41+
rescue TypeError
42+
ex = Exception.new e.message
43+
ex.set_backtrace e.backtrace
44+
Minitest::UnexpectedError.new ex
45+
end
46+
}
47+
end
48+
test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
49+
result = Marshal.dump(test_result)
4750
end
48-
test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
49-
result = Marshal.dump(test_result)
51+
52+
write.puts [result].pack("m")
53+
exit!
5054
end
5155

52-
write.puts [result].pack("m")
53-
exit!
56+
write.close
57+
result = read.read
58+
Process.wait2(pid)
59+
result.unpack1("m")
5460
end
55-
56-
write.close
57-
result = read.read
58-
Process.wait2(pid)
59-
result.unpack1("m")
6061
end
6162
end
6263

0 commit comments

Comments
 (0)