[
https://issues.apache.org/jira/browse/THRIFT-6112?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Dmytro Shteflyuk resolved THRIFT-6112.
--------------------------------------
Fix Version/s: 0.25.0
Resolution: Fixed
> Ruby Socket should reject duplicate opens
> -----------------------------------------
>
> Key: THRIFT-6112
> URL: https://issues.apache.org/jira/browse/THRIFT-6112
> Project: Thrift
> Issue Type: Bug
> Components: Ruby - Library
> Reporter: Dmytro Shteflyuk
> Assignee: Dmytro Shteflyuk
> Priority: Major
> Fix For: 0.25.0
>
> Time Spent: 40m
> Remaining Estimate: 0h
>
> h3. Problem
> Calling {{Thrift::Socket#open}} on an already-open transport creates a second
> TCP connection and replaces the transport's {{@handle}}. The first connection
> is not closed before its handle becomes unreachable through the transport.
> As a result, {{close}} only closes the replacement connection. The original
> connection remains open until some other owner closes it or Ruby eventually
> reclaims it.
> This ticket is scoped to the TCP {{Thrift::Socket}} transport. Transports
> that override {{open}} have separate lifecycle implementations and are not
> changed here.
> h3. Client impact
> Applications that accidentally open the same transport twice—for example,
> through overlapping connection setup or retry paths—can leave an unused TCP
> connection open on both the client and server. This consumes a file
> descriptor and may leave an unexpected server-side session active even after
> the transport itself is closed.
> h3. Reproduction
> From the repository root:
> {code:bash}
> ruby -Ilib/rb/lib /tmp/thrift_double_open.rb
> {code}
> With {{/tmp/thrift_double_open.rb}} containing:
> {code:ruby}
> require 'socket'
> require 'thrift'
> server = TCPServer.new('127.0.0.1', 0)
> transport = Thrift::Socket.new('127.0.0.1', server.local_address.ip_port)
> transport.open
> first_peer = server.accept
> first_handle = transport.handle
> transport.open
> second_peer = server.accept
> puts "first_handle_closed=#{first_handle.closed?}"
> puts "second_handle_same=#{transport.handle.equal?(first_handle)}"
> transport.close
> first_handle.close
> first_peer.close
> second_peer.close
> server.close
> {code}
> The current output is:
> {code}
> first_handle_closed=false
> second_handle_same=false
> {code}
> The transport has replaced its handle while leaving the first connection open.
> h3. Expected behavior
> Opening an already-open TCP transport should raise
> {{Thrift::TransportException}} with type {{ALREADY_OPEN}}. The existing live
> connection and handle should remain unchanged so the caller can continue
> using or explicitly close that transport.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)