JDK-6831518 : socket.connect() throws ConnectException instead of NoRouteToHostException
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: linux
  • CPU: generic
  • Submitted: 2009-04-17
  • Updated: 2012-07-23
Description
Sun internal bug corresponding to 
  https://bugs.openjdk.java.net/show_bug.cgi?id=100039

Comments
SUGGESTED FIX Original patch from omajid --- openjdk/jdk/src/solaris/native/java/net/PlainSocketImpl.c.orig 2008-11-25 04:06:19.000000000 -0500 +++ openjdk/jdk/src/solaris/native/java/net/PlainSocketImpl.c 2009-03-20 16:58:35.000000000 -0400 @@ -410,8 +410,16 @@ jlong prevTime = JVM_CurrentTimeMillis(env, 0); if (errno != EINPROGRESS) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", - "connect failed"); + if (errno == EHOSTUNREACH) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", + "Host unreachable"); + } else if (errno == ENETUNREACH) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", + "Network unreachable"); + } else { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", + "connect failed"); + } SET_BLOCKING(fd); return; } @@ -540,6 +548,9 @@ } else if (errno == EHOSTUNREACH) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", "Host unreachable"); + } else if (errno == ENETUNREACH) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", + "Network unreachable"); } else if (errno == EADDRNOTAVAIL) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", "Address not available");
23-07-2012

SUGGESTED FIX # Revised patch from Omair Majid diff -ruN openjdk/jdk/src/solaris/native/java/net/PlainSocketImpl.c openjdk/jdk/src/solaris/native/java/net/PlainSocketImpl.c --- openjdk/jdk/src/solaris/native/java/net/PlainSocketImpl.c 2011-02-28 11:06:49.000000000 -0500 +++ openjdk/jdk/src/solaris/native/java/net/PlainSocketImpl.c 2011-04-21 18:02:11.264531352 -0400 @@ -328,6 +328,9 @@ /* The result of the connection */ int connect_rv = -1; + /* whether an error occured early during non-blocking connect */ + int error_on_nonblocking_connect = 0; + if (IS_NULL(fdObj)) { JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); return; @@ -410,103 +413,103 @@ jlong prevTime = JVM_CurrentTimeMillis(env, 0); if (errno != EINPROGRESS) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", - "connect failed"); - SET_BLOCKING(fd); - return; - } + error_on_nonblocking_connect = 1; + } else { - /* - * Wait for the connection to be established or a - * timeout occurs. poll/select needs to handle EINTR in - * case lwp sig handler redirects any process signals to - * this thread. - */ - while (1) { - jlong newTime; + /* + * Wait for the connection to be established or a + * timeout occurs. poll/select needs to handle EINTR in + * case lwp sig handler redirects any process signals to + * this thread. + */ + while (1) { + jlong newTime; #ifndef USE_SELECT - { - struct pollfd pfd; - pfd.fd = fd; - pfd.events = POLLOUT; + { + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLOUT; - errno = 0; - connect_rv = NET_Poll(&pfd, 1, timeout); - } + errno = 0; + connect_rv = NET_Poll(&pfd, 1, timeout); + } #else - { - fd_set wr, ex; - struct timeval t; - - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - - FD_ZERO(&wr); - FD_SET(fd, &wr); - FD_ZERO(&ex); - FD_SET(fd, &ex); + { + fd_set wr, ex; + struct timeval t; + + t.tv_sec = timeout / 1000; + t.tv_usec = (timeout % 1000) * 1000; + + FD_ZERO(&wr); + FD_SET(fd, &wr); + FD_ZERO(&ex); + FD_SET(fd, &ex); - errno = 0; - connect_rv = NET_Select(fd+1, 0, &wr, &ex, &t); - } + errno = 0; + connect_rv = NET_Select(fd+1, 0, &wr, &ex, &t); + } #endif - if (connect_rv >= 0) { - break; - } - if (errno != EINTR) { - break; - } - - /* - * The poll was interrupted so adjust timeout and - * restart - */ - newTime = JVM_CurrentTimeMillis(env, 0); - timeout -= (newTime - prevTime); - if (timeout <= 0) { - connect_rv = 0; - break; - } - prevTime = newTime; + if (connect_rv >= 0) { + break; + } + if (errno != EINTR) { + break; + } - } /* while */ + /* + * The poll was interrupted so adjust timeout and + * restart + */ + newTime = JVM_CurrentTimeMillis(env, 0); + timeout -= (newTime - prevTime); + if (timeout <= 0) { + connect_rv = 0; + break; + } + prevTime = newTime; - if (connect_rv == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "connect timed out"); + } /* while */ - /* - * Timeout out but connection may still be established. - * At the high level it should be closed immediately but - * just in case we make the socket blocking again and - * shutdown input & output. - */ - SET_BLOCKING(fd); - JVM_SocketShutdown(fd, 2); - return; - } + if (connect_rv == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "connect timed out"); + + /* + * Timeout out but connection may still be established. + * At the high level it should be closed immediately but + * just in case we make the socket blocking again and + * shutdown input & output. + */ + SET_BLOCKING(fd); + JVM_SocketShutdown(fd, 2); + return; + } - /* has connection been established */ - optlen = sizeof(connect_rv); - if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv, - &optlen) <0) { - connect_rv = errno; + /* has connection been established */ + optlen = sizeof(connect_rv); + if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv, + &optlen) <0) { + connect_rv = errno; + } } } /* make socket blocking again */ SET_BLOCKING(fd); - /* restore errno */ - if (connect_rv != 0) { - errno = connect_rv; - connect_rv = JVM_IO_ERR; + if (!error_on_nonblocking_connect) { + /* restore errno */ + if (connect_rv != 0) { + errno = connect_rv; + connect_rv = JVM_IO_ERR; + } } } /* report the appropriate exception */ - if (connect_rv < 0) { + if (connect_rv < 0 || error_on_nonblocking_connect) { #ifdef __linux__ /* @@ -540,6 +543,9 @@ } else if (errno == EHOSTUNREACH) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", "Host unreachable"); + } else if (errno == ENETUNREACH) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", + "Network unreachable"); } else if (errno == EADDRNOTAVAIL) { NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", "Address not available");
23-07-2012