Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EHOSTUNREACH when a FTP connection cannot be established #5754

Closed
Adithya-copart opened this issue May 30, 2019 · 3 comments

Comments

@Adithya-copart
Copy link

commented May 30, 2019

Expected Behavior

Is it possible to make the error convey that the remote host is unavailable or unreachable like MRI does with EHOSTUNREACH?

I think that Errno::EBADF (Bad file descriptor - No message available) do not convey that the FTP server/host is unreachable.

I looked at #5709 (comment) and wonder if it is even possible to raise a EHOSTUNREACH.

Please feel free to close this if this cannot be considered an issue with JRuby.

JRuby:

jruby-9.2.7.0 :001 > require 'net/ftp'
 => true 
jruby-9.2.7.0 :002 > Net::FTP.open('example.com', 'test', 'password') do |ftp_conn|
jruby-9.2.7.0 :003 >     puts ftp_conn.nlst("*")
jruby-9.2.7.0 :004?>   end
Traceback (most recent call last):
       16: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/net/ftp.rb:163:in `open'
       15: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/net/ftp.rb:265:in `initialize'
       14: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/net/ftp.rb:367:in `connect'
       13: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/monitor.rb:226:in `mon_synchronize'
       12: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/net/ftp.rb:369:in `block in connect'
       11: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/net/ftp.rb:328:in `open_socket'
       10: from org/jruby/ext/timeout/Timeout.java:75:in `timeout'
        9: from org/jruby/ext/timeout/Timeout.java:82:in `timeout'
        8: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/net/ftp.rb:333:in `block in open_socket'
        7: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/socket.rb:638:in `tcp'
        6: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/socket.rb:229:in `foreach'
        5: from org/jruby/RubyArray.java:1792:in `each'
        4: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/socket.rb:648:in `block in tcp'
        3: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/socket.rb:139:in `connect'
        2: from /Users/adpentela/.rvm/rubies/jruby-9.2.7.0/lib/ruby/stdlib/socket.rb:69:in `connect_internal'
        1: from org/jruby/ext/socket/RubySocket.java:694:in `close'
Errno::EBADF (Bad file descriptor - No message available)

MRI:

irb(main):001:0> require 'net/ftp'
=> true
irb(main):002:0> Net::FTP.open('example.com', 'test', 'password') do |ftp_conn|
irb(main):003:1* puts ftp_conn.nlst("*")
irb(main):004:1> end
Traceback (most recent call last):
       16: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/net/ftp.rb:163:in `open'
       15: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/net/ftp.rb:163:in `new'
       14: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/net/ftp.rb:269:in `initialize'
       13: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/net/ftp.rb:370:in `connect'
       12: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/monitor.rb:230:in `mon_synchronize'
       11: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/net/ftp.rb:372:in `block in connect'
       10: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/net/ftp.rb:332:in `open_socket'
        9: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/timeout.rb:76:in `timeout'
        8: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/net/ftp.rb:337:in `block in open_socket'
        7: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/socket.rb:631:in `tcp'
        6: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/socket.rb:227:in `foreach'
        5: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/socket.rb:227:in `each'
        4: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/socket.rb:641:in `block in tcp'
        3: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/socket.rb:137:in `connect'
        2: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/socket.rb:64:in `connect_internal'
        1: from /Users/adpentela/.rvm/rubies/ruby-head/lib/ruby/2.7.0/socket.rb:64:in `connect'
Errno::EHOSTUNREACH (No route to host - connect(2) for [2606:2800:220:1:248:1893:25c8:1946]:21)
@headius

This comment has been minimized.

Copy link
Member

commented Jun 4, 2019

Confirmed on master.

@headius

This comment has been minimized.

Copy link
Member

commented Jun 4, 2019

The proper error does get raised, but then the logic in socket.rb attempts to close the not-quite-established connection and raises EBADF.

Tweaking the logic to not raise EBADF and show the intermediate errors exposes a further problem, however: we are not picking the right exception type for these errors. The first two here are the exceptions live near the close call, and the third is the one eventually re-raised with my tweaks:

#<Errno::EADDRINUSE: Address already in use - connect(2) - Operation timed out>
#<Errno::EADDRINUSE: Address already in use - connect(2) - No route to host>
Errno::EADDRINUSE: Address already in use - connect(2) - No route to host

These two errors should be ETIMEDOUT and EHOSTUNREACH.

@headius

This comment has been minimized.

Copy link
Member

commented Jun 4, 2019

Relates to #5709.

headius added a commit to headius/jruby that referenced this issue Jun 4, 2019

Check open status of channel when closing IO.
This allows failed connections from sockets (jruby#5709, jruby#5754) to
raise the actual socket error even though the logic in socket.rb
tries to close the failed socket.

This approach differs from jruby#5713 in that it modifies the final
flush logic to skip closed channels rather than modifying the
IO#closed? logic to do that same check.

headius added a commit to headius/jruby that referenced this issue Jun 4, 2019

@headius headius added this to the JRuby 9.2.8.0 milestone Jun 4, 2019

headius added a commit to headius/jruby that referenced this issue Jun 7, 2019

Reduce scope of close changes to only socket.
Because the case of a socket that fails to connect has special
behavior for us (the socket is closed or never opened by JDK) we
force it to clean up after a connect fails due to a
ConnectException. This may be valid for other failures but I am
limiting scope of this special case for now.

See jruby#5754.

headius added a commit that referenced this issue Jun 7, 2019

@headius headius closed this Jun 7, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.