Skip to content

Commit

Permalink
[GR-18163] Fix IO.pipe - don't use IO.new Ruby method
Browse files Browse the repository at this point in the history
PullRequest: truffleruby/3442
  • Loading branch information
andrykonchin committed Jul 28, 2022
2 parents af1b318 + 3957e88 commit ca0c55e
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Compatibility:
* Warn when a global variable is not initialized (#2595, @andrykonchin).
* Fix escaping of `/` by `Regexp#source` (#2569, @andrykonchin).
* Range literals of integers are now created at parse time like in CRuby (#2622, @aardvark179).
* Fix `IO.pipe` - allow overriding `IO.new` that is used to create new pipes (#2692, @andykonchin).

Performance:

Expand Down
12 changes: 12 additions & 0 deletions spec/ruby/core/io/fixtures/classes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ module IOSpecs
class SubIO < IO
end

class SubIOWithRedefinedNew < IO
def self.new(...)
ScratchPad << :redefined_new_called
super
end

def initialize(...)
ScratchPad << :call_original_initialize
super
end
end

def self.collector
Proc.new { |x| ScratchPad << x }
end
Expand Down
11 changes: 11 additions & 0 deletions spec/ruby/core/io/pipe_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@
@r.should be_an_instance_of(IOSpecs::SubIO)
@w.should be_an_instance_of(IOSpecs::SubIO)
end

it "does not use IO.new method to create pipes and allows its overriding" do
ScratchPad.record []

# so redefined .new is not called, but original #initialize is
@r, @w = IOSpecs::SubIOWithRedefinedNew.pipe
ScratchPad.recorded.should == [:call_original_initialize, :call_original_initialize] # called 2 times - for each pipe (r and w)

@r.should be_an_instance_of(IOSpecs::SubIOWithRedefinedNew)
@w.should be_an_instance_of(IOSpecs::SubIOWithRedefinedNew)
end
end

describe "IO.pipe" do
Expand Down
1 change: 0 additions & 1 deletion src/main/java/org/truffleruby/core/klass/ClassNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,6 @@ protected RubyClass newSingletonInstance(
}
}


@CoreMethod(names = "initialize", optional = 1)
public abstract static class InitializeNode extends CoreMethodArrayArgumentsNode {
@Specialization
Expand Down
6 changes: 4 additions & 2 deletions src/main/ruby/truffleruby/core/truffle/io_operations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,17 @@ def self.pipe_end_setup(io)
io
end

CLASS_NEW = Class.instance_method(:new)

def self.create_pipe(read_class, write_class, external = nil, internal = nil, options = nil)
fds = Truffle::FFI::MemoryPointer.new(:int, 2) do |ptr|
res = Truffle::POSIX.pipe(ptr)
Errno.handle if res == -1
ptr.read_array_of_int(2)
end

lhs = pipe_end_setup(read_class.new(fds[0], IO::RDONLY))
rhs = pipe_end_setup(write_class.new(fds[1], IO::WRONLY))
lhs = pipe_end_setup(CLASS_NEW.bind_call(read_class, fds[0], IO::RDONLY))
rhs = pipe_end_setup(CLASS_NEW.bind_call(write_class, fds[1], IO::WRONLY))

lhs.set_encoding external || Encoding.default_external,
internal || Encoding.default_internal, options
Expand Down

0 comments on commit ca0c55e

Please sign in to comment.