[JAVA-249] Java Driver cannot connect to 'localhost' when mongod is listening only on 127.0.0.1 (or "localhost") Created: 05/Jan/11  Updated: 18/Jun/12  Resolved: 14/May/12

Status: Closed
Project: Java Driver
Component/s: None
Affects Version/s: 2.3, 2.4
Fix Version/s: 2.8.0

Type: Bug Priority: Major - P3
Reporter: Brendan W. McAdams Assignee: Jeffrey Yemin
Resolution: Done Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Reproducible on Mac


Issue Links:
Duplicate
is duplicated by JAVA-577 It's not possible to shutdown databas... Closed
is duplicated by JAVA-430 Connection to mongodb://localhost:270... Closed
Related
related to JAVA-310 Driver reconnect does not detect netw... Closed
Backwards Compatibility: Fully Compatible

 Description   

Issue reported by user but reproducible by me.

When working with the 2.4 Java driver on Mac OS X (10.6.x) , where mongod listens on bind_ip 127.0.0.1 (also tried with 'localhost'), an empty Mongo constructor [Mongo()] connects. However, connecting to a hostname of "localhost" fails with:

com.mongodb.MongoInternalException: DBPort.findOne failed
at com.mongodb.DBPort.findOne(DBPort.java:153)
at com.mongodb.DBPort.runCommand(DBPort.java:159)
at com.mongodb.DBTCPConnector.testMaster(DBTCPConnector.java:371)
at com.mongodb.Mongo.<init>(Mongo.java:167)
at com.mongodb.Mongo.<init>(Mongo.java:151)
at com.mongodb.Mongo.<init>(Mongo.java:119)

Adding an explicit port number makes no difference.'

User reports they see same behavior if they specify a hostname of "127.0.0.1" although on my machine with a homebrew sourced 1.6.3 and 1.6.5 it functions with "127.0.0.1". If I remove the bind_ip declaration it works fine.

User reports behavior did not occur with the 2.1 Java driver — I've confirmed this. Uncertain if it happens on other platforms yet.



 Comments   
Comment by Jeffrey Yemin [ 18/Jun/12 ]

Closing for 2.8.0 release.

Comment by auto [ 14/May/12 ]

Author:

{u'login': u'jyemin', u'name': u'Jeff Yemin', u'email': u'jeff.yemin@10gen.com'}

Message: JAVA-249: Removed calls to InetAddress.getLocalHost and InetAddress.getAllByName, using InetAddress.getByName instead
Simplified code. Fixed Javadoc. Removed unused methods.
Made it thread-safe by making _address volatile
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/3b12c2ae2c208c9e78f75128154e7ead52f00aa1

Comment by Jeffrey Yemin [ 11/May/12 ]

I'm going to fix this by always using the getByName method in InetAddress.

Comment by Raman Gupta [ 13/Mar/12 ]

Yes, InetAddress.getLocalHost() does not mean "ip address associated with localhost". Rather, it means the "ip address associated with the local i.e. current host's name". Typically, this means that the IP address will be resolved to the external interface and not 127.0.0.1, which is not what a user would expect.

As noted by Jeff in the previous comment, there should not be an override for "localhost" to InetAddress.getLocalHost(). Rather InetAddress.getAllByName( host ); where host = "localhost" leaves the resolution of the name "localhost" to the OS, as the user would expect.

I just ran into this issue on a new CentOS EC2 instance, so this is not confined to Mac's, and funnily enough just submitted a pull request to GitHub with the same exact change Jeff proposed a couple of days ago: https://github.com/mongodb/mongo-java-driver/pull/65.

Comment by Jeffrey Yemin [ 10/Mar/12 ]

Using localhost works fine (on a Mac at least) if I comment out the first 3 lines of ServerAddress._getAddress

 
        if ( host.toLowerCase().equals("localhost") ){
            return new InetAddress[] { InetAddress.getLocalHost()};
        }
        
        return InetAddress.getAllByName( host );

InetAddress.getAllByName("localhost") will resolve to the loopback address, whereas InetAddress.getLocalHost() calls java.net.InetAddressImpl#getLocalHostName which does not always return "localhost", in which case it will try to look up the local host name in DNS, which will typically fail on a dev machine. For instance, on my dev machine it returns "jmpb.home"

Another thing we may want to do is to try all the InetAddress instances returned by InetAddress.getAllByName, instead of just the first one, until we find one that works.

Comment by Brendan W. McAdams [ 14/Jan/11 ]

Unfortunately, this is classified as either a Java-level or OS-level bug, and is not occurring within the Mongo driver.

The resolution error occurs in the layer between Java and the Operating System as it resolves the hostname and can't be addressed in Mongo's Java code.

Comment by Martin Grotzke [ 13/Jan/11 ]

We also encounter this on a gentoo, with java driver 2.4.

Changing localhost to 127.0.0.1 works, however, it should be possible to be able to connect with "localhost" to 127.0.0.1.

Comment by Brendan W. McAdams [ 05/Jan/11 ]

It turns out this is a quirk in the resolver on Mac and some Debians (per EH); localhost != 127.0.0.1 in these cases.

We should report a better error message to clarify that we couldn't resolve the host.

Comment by Brendan W. McAdams [ 05/Jan/11 ]

Confirmed as a Mac only bug, and it occurs in the java.net.InetSocketAddress constructor.

Looking to see if there are any crucial differences in the Mac JDK impl of ISA versus stock Sun.

Comment by Brendan W. McAdams [ 05/Jan/11 ]

The breakage is happening in line 43 of DBPort.java, the getSocketAddress() call on ServerAddress. I am confirming it doesn't break on other platforms and if it is mac only it is likely a bug on Mac's Java implementation.

The getSocketAddress() call is returning a different address than input — when it is called against a ServerAddress for 'localhost' it instead of returning localhost/127.0.0.1:27017 like it should, returns <system-public-hostname>/<system-public-ip>:<port>

If the MongoD is not listening on the public ip the connection fails.

Here is the debug dump from a Scala console:

scala> MongoConnection("127.0.0.1")
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Addr: 127.0.0.1:27017 Socket Addr: /127.0.0.1:27017
res0: com.mongodb.casbah.MongoConnection = com.mongodb.casbah.MongoConnection@47845cb3

scala> MongoConnection("localhost")
Addr: localhost:27017 Socket Addr: b-mac.local/10.4.1.111:27017
com.mongodb.MongoInternalException: DBPort.findOne failed
at com.mongodb.DBPort.findOne(DBPort.java:154)
at com.mongodb.DBPort.runCommand(DBPort.java:160)
at com.mongodb.DBTCPConnector.testMaster(DBTCPConnector.java:371)
at com.mongodb.Mongo.<init>(Mongo.java:167)
at com.mongodb.Mongo.<init>(Mongo.java:151)
at com.mongodb.Mongo.<init>(Mongo.java:119)
at com.mongodb.casbah.MongoConnection$.apply(MongoConnection.scala:150)
at .<init>(<console>:9)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
at RequestResult$.<clinit>(<console>)
at RequestResult$scala_repl_result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl...
scala> MongoConnection()
Addr: 127.0.0.1:27017 Socket Addr: /127.0.0.1:27017
res2: com.mongodb.casbah.MongoConnection = com.mongodb.casbah.MongoConnection@40199011

Comment by Brendan W. McAdams [ 05/Jan/11 ]

Reproduced issue on 2.3 java driver as well as 2.4; doesn't occur with 2.2 or earlier.

Comment by Brendan W. McAdams [ 05/Jan/11 ]

Mongod log shows in the case of the exception thrown connect attempts no connection is made to mongod, so this isn't the command failing but the actual connection.

Generated at Thu Feb 08 08:51:50 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.