Adding SocketChannel toString to connection exception messages
Steven Schlansker
stevenschlansker at gmail.com
Fri Dec 22 00:29:18 UTC 2017
> 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);
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg);
return;
} else {
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
@@ -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");
+ (env, JNU_JAVANETPKG "SocketException", errmsg);
}
return;
}
@@ -479,6 +485,15 @@
}
}
+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
More information about the core-libs-dev
mailing list