Skip to content

Commit ca0c55e

Browse files
committed
[GR-18163] Fix IO.pipe - don't use IO.new Ruby method
PullRequest: truffleruby/3442
2 parents af1b318 + 3957e88 commit ca0c55e

File tree

5 files changed

+28
-3
lines changed

5 files changed

+28
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Compatibility:
1717
* Warn when a global variable is not initialized (#2595, @andrykonchin).
1818
* Fix escaping of `/` by `Regexp#source` (#2569, @andrykonchin).
1919
* Range literals of integers are now created at parse time like in CRuby (#2622, @aardvark179).
20+
* Fix `IO.pipe` - allow overriding `IO.new` that is used to create new pipes (#2692, @andykonchin).
2021

2122
Performance:
2223

spec/ruby/core/io/fixtures/classes.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@ module IOSpecs
77
class SubIO < IO
88
end
99

10+
class SubIOWithRedefinedNew < IO
11+
def self.new(...)
12+
ScratchPad << :redefined_new_called
13+
super
14+
end
15+
16+
def initialize(...)
17+
ScratchPad << :call_original_initialize
18+
super
19+
end
20+
end
21+
1022
def self.collector
1123
Proc.new { |x| ScratchPad << x }
1224
end

spec/ruby/core/io/pipe_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@
2525
@r.should be_an_instance_of(IOSpecs::SubIO)
2626
@w.should be_an_instance_of(IOSpecs::SubIO)
2727
end
28+
29+
it "does not use IO.new method to create pipes and allows its overriding" do
30+
ScratchPad.record []
31+
32+
# so redefined .new is not called, but original #initialize is
33+
@r, @w = IOSpecs::SubIOWithRedefinedNew.pipe
34+
ScratchPad.recorded.should == [:call_original_initialize, :call_original_initialize] # called 2 times - for each pipe (r and w)
35+
36+
@r.should be_an_instance_of(IOSpecs::SubIOWithRedefinedNew)
37+
@w.should be_an_instance_of(IOSpecs::SubIOWithRedefinedNew)
38+
end
2839
end
2940

3041
describe "IO.pipe" do

src/main/java/org/truffleruby/core/klass/ClassNodes.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,6 @@ protected RubyClass newSingletonInstance(
283283
}
284284
}
285285

286-
287286
@CoreMethod(names = "initialize", optional = 1)
288287
public abstract static class InitializeNode extends CoreMethodArrayArgumentsNode {
289288
@Specialization

src/main/ruby/truffleruby/core/truffle/io_operations.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,17 @@ def self.pipe_end_setup(io)
9999
io
100100
end
101101

102+
CLASS_NEW = Class.instance_method(:new)
103+
102104
def self.create_pipe(read_class, write_class, external = nil, internal = nil, options = nil)
103105
fds = Truffle::FFI::MemoryPointer.new(:int, 2) do |ptr|
104106
res = Truffle::POSIX.pipe(ptr)
105107
Errno.handle if res == -1
106108
ptr.read_array_of_int(2)
107109
end
108110

109-
lhs = pipe_end_setup(read_class.new(fds[0], IO::RDONLY))
110-
rhs = pipe_end_setup(write_class.new(fds[1], IO::WRONLY))
111+
lhs = pipe_end_setup(CLASS_NEW.bind_call(read_class, fds[0], IO::RDONLY))
112+
rhs = pipe_end_setup(CLASS_NEW.bind_call(write_class, fds[1], IO::WRONLY))
111113

112114
lhs.set_encoding external || Encoding.default_external,
113115
internal || Encoding.default_internal, options

0 commit comments

Comments
 (0)