[ 
https://issues.apache.org/jira/browse/THRIFT-6191?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jens Geyer reassigned THRIFT-6191:
----------------------------------

    Assignee: Jens Geyer

> C++ server sockets and TSocket resolve the same host with different 
> getaddrinfo flags
> -------------------------------------------------------------------------------------
>
>                 Key: THRIFT-6191
>                 URL: https://issues.apache.org/jira/browse/THRIFT-6191
>             Project: Thrift
>          Issue Type: Bug
>          Components: C++ - Library
>            Reporter: Jens Geyer
>            Assignee: Jens Geyer
>            Priority: Major
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> h2. What happens
> {{TServerSocket::listen()}} and {{TNonblockingServerSocket::listen()}} 
> resolve the bind address
> with {{AI_PASSIVE | AI_V4MAPPED}}. {{TSocket::open()}} resolves the connect 
> address with
> {{AI_PASSIVE | AI_ADDRCONFIG}}.
> On a host where {{/etc/hosts}} lists {{::1 localhost}} but no IPv6 address is 
> configured on
> {{lo}} -- a default Docker container, for instance -- the two disagree about 
> what
> {{"localhost"}} means:
> ||Caller||Flags||First address returned||
> |{{TServerSocket::listen()}}|{{AI_PASSIVE}} + {{AI_V4MAPPED}}|{{::1}}, and 
> the bind succeeds|
> |{{TSocket::open()}}|{{AI_PASSIVE}} + {{AI_ADDRCONFIG}}|{{127.0.0.1}}|
> A C++ server bound to {{"localhost"}} therefore listens on {{::1}} while a 
> C++ client connecting
> to {{"localhost"}} on the same machine dials {{127.0.0.1}}, and the connect 
> fails with
> {{ECONNREFUSED}}.
> The {{IPV6_V6ONLY=0}} that {{listen()}} sets on an {{AF_INET6}} socket does 
> not rescue it: the
> bind is to {{::1}} specifically rather than to {{::}}, and a v4-mapped 
> address is not covered by
> that.
> h2. Where it shows
> {{lib/cpp/test/TServerSocketTest.cpp}}'s {{test_bind_to_address}} fails in 
> exactly this
> environment, and has nothing to do with the test itself:
> {noformat}
> unknown location(0): fatal error: in "TServerSocketTest/test_bind_to_address":
> apache::thrift::transport::TTransportException: connect() failed: Connection 
> refused
> {noformat}
> CI does not catch it. GitHub runners have {{::1}} on {{lo}}, so 
> {{AI_ADDRCONFIG}} returns IPv6
> for the client as well and both sides agree again.
> h2. Measured
> A standalone probe that resolves and binds with each flag set and then 
> connects, run in a
> container with no IPv6 address on {{lo}}:
> {noformat}
> server pre-0.14.0 (AI_PASSIVE|AI_ADDRCONFIG)   server binds IPv4, client 
> tries IPv4 -> CONNECTED
> server today      (AI_PASSIVE|AI_V4MAPPED)     server binds IPv6, client 
> tries IPv4 -> Connection refused
> server today, without IPV6_V6ONLY=0            server binds IPv6, client 
> tries IPv4 -> Connection refused
> {noformat}
> h2. When it changed
> Last worked in 0.13.0. THRIFT-5186 removed {{AI_ADDRCONFIG}} from the server 
> sockets in
> {{9b9567b23}} (2020-04-27), first released in 0.14.0. That change was right 
> on its own terms --
> {{AI_ADDRCONFIG}} does not count the loopback address as a configured 
> address, so a host with no
> other address could not resolve localhost at all. The client side kept the 
> flag, and the
> asymmetry is what breaks.
> THRIFT-5880 ({{25202e1b0}}, 0.23.0) later gave {{TSocket::open()}} a retry 
> without
> {{AI_ADDRCONFIG}}, but it is conditional on {{EAI_NODATA}} / 
> {{EAI_ADDRFAMILY}} and does not fire
> here, because the first call succeeds.
> h2. Possible directions
> Not decided, and worth discussing before anyone writes a patch:
> * bind {{::}} rather than the first resolved address, keeping 
> {{IPV6_V6ONLY=0}};
> * try every resolved address instead of stopping at the first that binds;
> * drop {{AI_ADDRCONFIG}} on the client too, matching what THRIFT-5186 did for 
> the server.
> {{TServerSocket}} and {{TNonblockingServerSocket}} carry the same line and 
> would need the same
> treatment.
> _Filed with AI assistance (Claude Opus 5); reviewed and filed by Jens Geyer._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to