Adding SocketChannel toString to connection exception messages (original) (raw)
Steven Schlansker stevenschlansker at gmail.com
Fri Dec 22 00:29:18 UTC 2017
- Previous message: Adding SocketChannel toString to connection exception messages
- Next message: Adding SocketChannel toString to connection exception messages
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Dec 21, 2017, at 11:11 AM, Steven Schlansker <stevenschlansker at gmail.com> wrote:
What if ConnectException included the attempted hostname / IP / port SocketAddress? java.net.ConnectException: Connection to 'foo.mycorp.com[10.x.x.x]:12345' refused Much more useful! This could also be extended to various other socket exceptions.
I started hacking around with this, first with PlainSocketImpl only. I apologize in advance for what is likely to be terrible JNI style, as I don't have much experience with it and I omitted any error handling for the POC - but I think it proves that this isn't too big of a project, as I would want to cover SocketChannelImpl and maybe UnixAsynchronousSocketChannelImpl and call it good enough for my uses.
Behold!
[me at myhost]% java pkg.SocketFail java.net.ConnectException: Connection refused (Connection refused)
[me at myhost]% ~/code/jdk10/build/macosx-x86_64-normal-server-release/jdk/bin/java pkg.SocketFail java.net.ConnectException: Connection refused (Connection refused: localhost/127.0.0.1:12345)
Am I correct that the best path towards acceptance for this kind of change is to target jdk10 and then beg for a backport to jdk9u? Thanks again for considering this improvement! WIP patch below inline.
diff --git a/src/java.base/unix/native/libnet/PlainSocketImpl.c b/src/java.base/unix/native/libnet/PlainSocketImpl.c --- a/src/java.base/unix/native/libnet/PlainSocketImpl.c +++ b/src/java.base/unix/native/libnet/PlainSocketImpl.c @@ -217,6 +217,9 @@ (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); }
+// private helper for socketConnect to describe errors +static void sockErrDescribe(JNIEnv env, char errbuf, char* msg, jobject ia, jint port); + /*
- inetAddress is the address object passed to the socket connect
- call. @@ -230,6 +233,7 @@ jobject iaObj, jint port, jint timeout)
{
char errmsg[256]; jint localport = (env)->GetIntField(env, this, psi_localportID); int len = 0; / fdObj is the FileDescriptor field on this */ @@ -249,7 +253,8 @@ int connect_rv = -1;
if (IS_NULL(fdObj)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
sockErrDescribe(env, errmsg, "Socket closed", iaObj, port);
} else { fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); return;
@@ -329,8 +334,8 @@ jlong prevNanoTime = JVM_NanoTime(env, 0);
if (errno != EINPROGRESS) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
"connect failed");
sockErrDescribe(env, errmsg, "connect failed", iaObj, port);
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", errmsg); SET_BLOCKING(fd); return; }
@@ -372,8 +377,8 @@ } /* while */
if (connect_rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"connect timed out");
sockErrDescribe(env, errmsg, "connect timed out", iaObj, port);
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", errmsg); /* * Timeout out but connection may still be established.
@@ -419,36 +424,37 @@ * a more descriptive exception text is used. */ if (connect_rv == -1 && errno == EINVAL) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Invalid argument or cannot assign requested address");
sockErrDescribe(errmsg, "Invalid argument or cannot assign requested address", iaObj, port)
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); return; }
#endif #if defined(EPROTO) if (errno == EPROTO) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ProtocolException",
"Protocol error");
sockErrDescribe(env, errmsg, "Protocol error", iaObj, port);
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ProtocolException", errmsg); return; }
#endif if (errno == ECONNREFUSED) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
"Connection refused");
sockErrDescribe(env, errmsg, "Connection refused", iaObj, port);
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", errmsg); } else if (errno == ETIMEDOUT) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
"Connection timed out");
sockErrDescribe(env, errmsg, "Connection timed out", iaObj, port);
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException", errmsg); } else if (errno == EHOSTUNREACH) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
"Host unreachable");
sockErrDescribe(env, errmsg, "Host unreachable", iaObj, port);
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", errmsg); } else if (errno == EADDRNOTAVAIL) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
"Address not available");
sockErrDescribe(env, errmsg, "Address not available", iaObj, port);
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException", errmsg); } else if ((errno == EISCONN) || (errno == EBADF)) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Socket closed");
sockErrDescribe(env, errmsg, "Socket closed", iaObj, port);
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); } else {
sockErrDescribe(env, errmsg, "connect failed", iaObj, port); JNU_ThrowByNameWithMessageAndLastError
(env, JNU_JAVANETPKG "SocketException", "connect failed");
} @@ -479,6 +485,15 @@ } }(env, JNU_JAVANETPKG "SocketException", errmsg); } return;
+static void sockErrDescribe(JNIEnv env, char errbuf, char* msg, jobject ia, jint port) {
- jclass obj = (*env)->FindClass(env, "java/lang/Object");
- jmethodID toStr = (*env)->GetMethodID(env, obj, "toString", "()Ljava/lang/String;");
- jstring iaJstr = (*env)->CallObjectMethod(env, ia, toStr);
- const char *iaStr = (*env)->GetStringUTFChars(env, iaJstr, 0);
- jio_snprintf(errbuf, 128, "%s: %s:%d", msg, iaStr, port);
- (*env)->ReleaseStringUTFChars(env, iaJstr, iaStr);
+} + /*
- Class: java_net_PlainSocketImpl
- Method: socketBind
- Previous message: Adding SocketChannel toString to connection exception messages
- Next message: Adding SocketChannel toString to connection exception messages
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]