Project

General

Profile

Actions

Bug #9247

closed

Bugs in socket.rb (exception retrieval)

Added by ko1 (Koichi Sasada) over 10 years ago. Updated about 10 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 2.1.0dev (2013-12-13 trunk 44170) [i386-mswin32_110]
[ruby-core:59088]

Description

Ruby 2.1 (trunk) 2.0 and 1.9.3 both has a bug to retrieve exception.
In the following code, opened socket is always closed.

require 'socket'
ai = Addrinfo.tcp(nil, 12345)
begin
raise
rescue
p ai.listen #=> #Socket:(closed)
end

This is because in socket.rb, there are such error handling code:

creates a listening socket bound to self.

def listen(backlog=Socket::SOMAXCONN)
sock = Socket.new(self.pfamily, self.socktype, self.protocol)
begin
sock.ipv6only! if self.ipv6?
sock.setsockopt(:SOCKET, :REUSEADDR, 1)
sock.bind(self)
sock.listen(backlog)
if block_given?
yield sock
else
sock
end
ensure
### THIS LINE CLOSE `sock' every time when $! is not nil
sock.close if !sock.closed? && (block_given? || $!)
end
end

There are similar code in socket.rb.

akr-san already knows this issue.
This ticket is to note issues.

We realize this issue because webrick use this feature from 2.1.
The following code no longer works on 2.1.

begin
require 'xyzzy' # something like webrick
rescue LoadError
require 'webrick'
server = WEBrick::HTTPServer.new(Port: 12345)
end

Because $! is an instance of LoadError.

Updated by mrkn (Kenta Murata) over 10 years ago

  • Description updated (diff)

I think the following code can reproduce the full cases:

https://gist.github.com/mrkn/7945798

require 'socket'

Addrinfo#connect_internal

puts "(1) Addrinfo#connect (connect_internal)"
begin
raise
rescue
p Addrinfo.tcp('www.ruby-lang.org', 80).connect
end

Addrinfo.bind

puts "\n(2) Addrinfo#bind"
begin
ai = Addrinfo.tcp(nil, 11229)
raise
rescue
begin
p ai.bind
end
end

Addrinfo.listen

puts "\n(3) Addrinfo#listen"
begin
ai = Addrinfo.tcp(nil, 11228)
raise
rescue
begin
p ai.listen
end
end

Socket.ip_sockets_port0

puts "\n(4) Socket.tcp_server_sockets (ip_sockets_port0)"
begin
raise
rescue
begin
Socket.tcp_server_sockets(0)
rescue IOError
$stderr.puts "#{$!.class}: #{$!}", $!.backtrace
end
end

Updated by mrkn (Kenta Murata) over 10 years ago

  • Status changed from Open to Assigned
Actions #3

Updated by akr (Akira Tanaka) over 10 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r44184.
Koichi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


  • ext/socket/lib/socket.rb: Don't test $! in "ensure" clause because
    it may be set before the body.
    Reported by ko1 and mrkn. [ruby-core:59088] [Bug #9247]

  • lib/cgi/core.rb: Ditto.

  • lib/drb/ssl.rb: Ditto.

Updated by ko1 (Koichi Sasada) over 10 years ago

  • Backport changed from 1.9.3: UNKNOWN, 2.0.0: UNKNOWN to 1.9.3: REQUIRED, 2.0.0: REQUIRED

Updated by ko1 (Koichi Sasada) over 10 years ago

  • Status changed from Closed to Assigned
  • Assignee changed from akr (Akira Tanaka) to nagachika (Tomoyuki Chikanaga)

Updated by nagachika (Tomoyuki Chikanaga) over 10 years ago

  • Backport changed from 1.9.3: REQUIRED, 2.0.0: REQUIRED to 1.9.3: REQUIRED, 2.0.0: DONE

r44184 was backported to ruby_2_0_0 at r44390.

Updated by nagachika (Tomoyuki Chikanaga) over 10 years ago

  • Assignee changed from nagachika (Tomoyuki Chikanaga) to usa (Usaku NAKAMURA)

Updated by hsbt (Hiroshi SHIBATA) about 10 years ago

  • Target version changed from 2.1.0 to 2.2.0

Updated by usa (Usaku NAKAMURA) about 10 years ago

  • Status changed from Assigned to Closed
  • Target version deleted (2.2.0)
  • Backport changed from 1.9.3: REQUIRED, 2.0.0: DONE to 1.9.3: DONE, 2.0.0: DONE

backported into ruby_1_9_3 at r44767.

BTW, this problem was fixed before releacing ruby 2.1, so all active branches are now OK.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0