Skip to content

Instantly share code, notes, and snippets.

@raboof
Created October 9, 2015 20:17
Show Gist options
  • Save raboof/e971a9c62fdcfffa6e7d to your computer and use it in GitHub Desktop.
Save raboof/e971a9c62fdcfffa6e7d to your computer and use it in GitHub Desktop.
What if... java BindExceptions would actually tell you *which* address is already in use?
diff -r d3b0a91b15b3 make/mapfiles/libjava/mapfile-vers
--- a/make/mapfiles/libjava/mapfile-vers Tue Oct 06 12:54:22 2015 +0300
+++ b/make/mapfiles/libjava/mapfile-vers Fri Oct 09 22:15:40 2015 +0200
@@ -56,6 +56,7 @@
JNU_ThrowArrayIndexOutOfBoundsException;
JNU_ThrowByName;
JNU_ThrowByNameWithLastError;
+ JNU_ThrowByNameWithLastErrorAndMsg;
JNU_ThrowClassNotFoundException;
JNU_ThrowIllegalAccessError;
JNU_ThrowIllegalAccessException;
diff -r d3b0a91b15b3 src/share/native/common/jni_util.c
--- a/src/share/native/common/jni_util.c Tue Oct 06 12:54:22 2015 +0300
+++ b/src/share/native/common/jni_util.c Fri Oct 09 22:15:40 2015 +0200
@@ -149,7 +149,7 @@
/* Throw an exception by name, using the string returned by
- * JVM_LastErrorString for the detail string. If the last-error
+ * JVM_GetLastErrorString for the detail string. If the last-error
* string is NULL, use the given default detail string.
*/
JNIEXPORT void JNICALL
@@ -174,6 +174,47 @@
}
}
+/* Throw an exception by name, using the string returned by
+ * JVM_GetLastErrorString along with a given message. If the
+ * msg is NULL, only the last error is added. If the last-error
+ * string is NULL, use the given default detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowByNameWithLastErrorAndMsg(JNIEnv *env, const char *name,
+ const char *msg,
+ const char *defaultError)
+{
+ char buf[1024];
+ size_t n = 0;
+ if (msg != NULL) {
+ n = strlen(msg);
+ if (n >= sizeof(buf))
+ n = sizeof(buf) - 1;
+ strncpy(buf, msg, n);
+ buf[n] = '\0';
+ }
+
+ if (n < sizeof(buf)-1) {
+ size_t j = JVM_GetLastErrorString(buf + n, sizeof(buf) - n);
+ n = n + j;
+ }
+
+ if (n > 0) {
+ jstring s = JNU_NewStringPlatform(env, buf);
+ if (s != NULL) {
+ jobject x = JNU_NewObjectByName(env, name,
+ "(Ljava/lang/String;)V", s);
+ if (x != NULL) {
+ (*env)->Throw(env, x);
+ }
+ }
+ }
+ if (!(*env)->ExceptionOccurred(env)) {
+ JNU_ThrowByName(env, name, defaultError);
+ }
+}
+
+
/* Throw an IOException, using the last-error string for the detail
* string. If the last-error string is NULL, use the given default
* detail string.
diff -r d3b0a91b15b3 src/share/native/common/jni_util.h
--- a/src/share/native/common/jni_util.h Tue Oct 06 12:54:22 2015 +0300
+++ b/src/share/native/common/jni_util.h Fri Oct 09 22:15:40 2015 +0200
@@ -98,13 +98,23 @@
JNU_ThrowInstantiationException(JNIEnv *env, const char *msg);
/* Throw an exception by name, using the string returned by
- * JVM_LastErrorString for the detail string. If the last-error
+ * JVM_GetLastErrorString for the detail string. If the last-error
* string is NULL, use the given default detail string.
*/
JNIEXPORT void JNICALL
JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
const char *defaultMessage);
+/* Throw an exception by name, using the string returned by
+ * JVM_GetLastErrorString along with a given message. If the
+ * msg is NULL, only the last error is added. If the last-error
+ * string is NULL, use the given default detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowByNameWithLastErrorAndMsg(JNIEnv *env, const char *name,
+ const char *msg,
+ const char *defaultError);
+
/* Throw an IOException, using the last-error string for the detail
* string. If the last-error string is NULL, use the given default
* detail string.
diff -r d3b0a91b15b3 src/solaris/native/sun/nio/ch/Net.c
--- a/src/solaris/native/sun/nio/ch/Net.c Tue Oct 06 12:54:22 2015 +0300
+++ b/src/solaris/native/sun/nio/ch/Net.c Fri Oct 09 22:15:40 2015 +0200
@@ -27,8 +27,10 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
+#include <stdio.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
+#include <arpa/inet.h>
#include "jni.h"
#include "jni_util.h"
@@ -319,7 +321,23 @@
rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
if (rv != 0) {
- handleSocketError(env, errno);
+ char msg[256];
+ char addr[256];
+ switch (((struct sockaddr *)&sa)->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in*)&sa;
+ snprintf(msg, sizeof(msg), "%s:%d: ", inet_ntop(sin->sin_family, &(sin->sin_addr), addr, sizeof(addr)), port);
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sin = (struct sockaddr_in6*)&sa;
+ snprintf(msg, sizeof(msg), "%s:%d: ", inet_ntop(sin->sin6_family, &(sin->sin6_addr), addr, sizeof(addr)), port);
+ break;
+ }
+ default:
+ snprintf(msg, sizeof(msg), ":%d: ", port);
+ }
+ handleSocketErrorWithMsg(env, msg, errno);
}
}
@@ -806,10 +824,8 @@
}
-/* Declared in nio_util.h */
-
jint
-handleSocketError(JNIEnv *env, jint errorValue)
+handleSocketErrorWithMsg(JNIEnv *env, const char *msg, jint errorValue)
{
char *xn;
switch (errorValue) {
@@ -838,6 +854,12 @@
break;
}
errno = errorValue;
- JNU_ThrowByNameWithLastError(env, xn, "NioSocketError");
+ JNU_ThrowByNameWithLastErrorAndMsg(env, xn, msg, "NioSocketError");
return IOS_THROWN;
}
+
+jint
+handleSocketError(JNIEnv *env, jint errorValue)
+{
+ return handleSocketErrorWithMsg(env, NULL, errorValue);
+}
diff -r d3b0a91b15b3 src/solaris/native/sun/nio/ch/nio_util.h
--- a/src/solaris/native/sun/nio/ch/nio_util.h Tue Oct 06 12:54:22 2015 +0300
+++ b/src/solaris/native/sun/nio/ch/nio_util.h Fri Oct 09 22:15:40 2015 +0200
@@ -50,4 +50,5 @@
/* Defined in Net.c */
+jint handleSocketErrorWithMsg(JNIEnv *env, const char *msg, jint errorValue);
jint handleSocketError(JNIEnv *env, jint errorValue);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment