changeset 11053:9e7d9568678d

8133249: Occasional SIGSEGV: non thread-safe use of strerr in get LastErrorString Reviewed-by: coffeys, igerasim
author robm
date Sat, 17 Oct 2015 21:55:25 +0100
parents 8b25e4b098ca
children bdbb8a650d90 9ad796b3ce4d
files make/lib/CoreLibraries.gmk make/mapfiles/libjava/mapfile-vers src/share/native/common/jni_util.h src/share/native/java/util/zip/zip_util.c src/solaris/native/common/jni_util_md.c src/solaris/native/java/io/io_util_md.c src/solaris/native/java/lang/UNIXProcess_md.c src/solaris/native/java/net/PlainDatagramSocketImpl.c src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c src/windows/native/common/jni_util_md.c src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c
diffstat 11 files changed, 67 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/make/lib/CoreLibraries.gmk	Wed Oct 14 13:28:29 2015 +0100
+++ b/make/lib/CoreLibraries.gmk	Sat Oct 17 21:55:25 2015 +0100
@@ -205,6 +205,7 @@
         -framework Foundation \
         -framework Security -framework SystemConfiguration, \
     LDFLAGS_SUFFIX_windows := -export:winFileHandleOpen -export:handleLseek \
+        -export:getErrorString \
         jvm.lib $(BUILD_LIBFDLIBM) $(WIN_VERIFY_LIB) \
         shell32.lib delayimp.lib -DELAYLOAD:shell32.dll \
         advapi32.lib version.lib, \
--- a/make/mapfiles/libjava/mapfile-vers	Wed Oct 14 13:28:29 2015 +0100
+++ b/make/mapfiles/libjava/mapfile-vers	Sat Oct 17 21:55:25 2015 +0100
@@ -284,6 +284,8 @@
 		
                 # ZipFile.c needs this one
 		throwFileNotFoundException;
+                # zip_util.c needs this
+		getErrorString;
 
 #		Java_sun_misc_VM_getState;			threads.c
 #		Java_sun_misc_VM_threadsSuspended;		threads.c
--- a/src/share/native/common/jni_util.h	Wed Oct 14 13:28:29 2015 +0100
+++ b/src/share/native/common/jni_util.h	Sat Oct 17 21:55:25 2015 +0100
@@ -391,6 +391,7 @@
 void buildJniFunctionName(const char *sym, const char *cname,
                           char *jniEntryName);
 
+extern int getErrorString(int err, char *buf, size_t len);
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
--- a/src/share/native/java/util/zip/zip_util.c	Wed Oct 14 13:28:29 2015 +0100
+++ b/src/share/native/java/util/zip/zip_util.c	Sat Oct 17 21:55:25 2015 +0100
@@ -1449,6 +1449,7 @@
 ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
 {
     char *msg;
+    char tmpbuf[1024];
 
     strcpy(entryname, entry->name);
     if (entry->csize == 0) {
@@ -1467,8 +1468,11 @@
             msg = zip->msg;
             ZIP_Unlock(zip);
             if (n == -1) {
-                jio_fprintf(stderr, "%s: %s\n", zip->name,
-                            msg != 0 ? msg : strerror(errno));
+                if (msg == 0) {
+                    getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+                    msg = tmpbuf;
+                }
+                jio_fprintf(stderr, "%s: %s\n", zip->name, msg);
                 return JNI_FALSE;
             }
             buf += n;
@@ -1481,8 +1485,11 @@
             if ((msg == NULL) || (*msg == 0)) {
                 msg = zip->msg;
             }
-            jio_fprintf(stderr, "%s: %s\n", zip->name,
-                        msg != 0 ? msg : strerror(errno));
+            if (msg == 0) {
+                getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+                msg = tmpbuf;
+            }
+            jio_fprintf(stderr, "%s: %s\n", zip->name, msg);
             return JNI_FALSE;
         }
     }
--- a/src/solaris/native/common/jni_util_md.c	Wed Oct 14 13:28:29 2015 +0100
+++ b/src/solaris/native/common/jni_util_md.c	Sat Oct 17 21:55:25 2015 +0100
@@ -37,6 +37,13 @@
     return NULL;
 }
 
+#if defined(LINUX) && (defined(_GNU_SOURCE) || \
+         (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE < 200112L \
+             && defined(_XOPEN_SOURCE) && _XOPEN_SOURCE < 600))
+extern int __xpg_strerror_r(int, char *, size_t);
+#define strerror_r(a, b, c) __xpg_strerror_r((a), (b), (c))
+#endif
+
 void* getProcessHandle() {
     static void *procHandle = NULL;
     if (procHandle != NULL) {
@@ -59,3 +66,9 @@
     }
 }
 
+int
+getErrorString(int err, char *buf, size_t len)
+{
+    if (err == 0 || len < 1) return 0;
+    return strerror_r(err, buf, len);
+}
--- a/src/solaris/native/java/io/io_util_md.c	Wed Oct 14 13:28:29 2015 +0100
+++ b/src/solaris/native/java/io/io_util_md.c	Sat Oct 17 21:55:25 2015 +0100
@@ -216,13 +216,6 @@
 getLastErrorString(char *buf, size_t len)
 {
     if (errno == 0 || len < 1) return 0;
-
-    const char *err = strerror(errno);
-    size_t n = strlen(err);
-    if (n >= len)
-        n = len - 1;
-
-    strncpy(buf, err, n);
-    buf[n] = '\0';
-    return n;
+    getErrorString(errno, buf, len);
+    return strlen(buf);
 }
--- a/src/solaris/native/java/lang/UNIXProcess_md.c	Wed Oct 14 13:28:29 2015 +0100
+++ b/src/solaris/native/java/lang/UNIXProcess_md.c	Sat Oct 17 21:55:25 2015 +0100
@@ -292,12 +292,13 @@
     static const char * const format = "error=%d, %s";
     const char *detail = defaultDetail;
     char *errmsg;
+    char tmpbuf[1024];
     jstring s;
 
     if (errnum != 0) {
-        const char *s = strerror(errnum);
-        if (strcmp(s, "Unknown error") != 0)
-            detail = s;
+        int ret = getErrorString(errnum, tmpbuf, sizeof(tmpbuf));
+        if (ret != EINVAL)
+            detail = tmpbuf;
     }
     /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
     errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
--- a/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Wed Oct 14 13:28:29 2015 +0100
+++ b/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Sat Oct 17 21:55:25 2015 +0100
@@ -954,6 +954,7 @@
                                                            jobject this) {
     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
     int arg, fd, t = 1;
+    char tmpbuf[1024];
 #ifdef AF_INET6
     int domain = ipv6_available() ? AF_INET6 : AF_INET;
 #else
@@ -989,14 +990,14 @@
     arg = 65507;
     if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_SNDBUF,
                        (char *)&arg, sizeof(arg)) < 0) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        strerror(errno));
+        getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
         return;
     }
     if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_RCVBUF,
                        (char *)&arg, sizeof(arg)) < 0) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        strerror(errno));
+        getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
         return;
     }
 #endif /* __APPLE__ */
@@ -1004,15 +1005,16 @@
      setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof(int));
 
 #if defined(__linux__)
-     arg = 0;
-     int level = (domain == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;
-     if ((setsockopt(fd, level, IP_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0) &&
-         (errno != ENOPROTOOPT)) {
-         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                         strerror(errno));
-         close(fd);
-         return;
-     }
+    arg = 0;
+    int level = (domain == AF_INET6) ? IPPROTO_IPV6 : IPPROTO_IP;
+    if ((setsockopt(fd, level, IP_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0) &&
+          (errno != ENOPROTOOPT))
+    {
+        getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", tmpbuf);
+        close(fd);
+        return;
+    }
 #endif
 
 #if defined (__linux__) && defined (AF_INET6)
--- a/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c	Wed Oct 14 13:28:29 2015 +0100
+++ b/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.c	Sat Oct 17 21:55:25 2015 +0100
@@ -308,21 +308,15 @@
 JNIEXPORT jbyteArray
 Java_sun_nio_fs_UnixNativeDispatcher_strerror(JNIEnv* env, jclass this, jint error)
 {
-    char* msg;
+    char tmpbuf[1024];
     jsize len;
     jbyteArray bytes;
 
-#ifdef _AIX
-    /* strerror() is not thread-safe on AIX so we have to use strerror_r() */
-    char buffer[256];
-    msg = (strerror_r((int)error, buffer, 256) == 0) ? buffer : "Error while calling strerror_r";
-#else
-    msg = strerror((int)error);
-#endif
-    len = strlen(msg);
+    getErrorString((int)errno, tmpbuf, sizeof(tmpbuf));
+    len = strlen(tmpbuf);
     bytes = (*env)->NewByteArray(env, len);
     if (bytes != NULL) {
-        (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)msg);
+        (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)tmpbuf);
     }
     return bytes;
 }
--- a/src/windows/native/common/jni_util_md.c	Wed Oct 14 13:28:29 2015 +0100
+++ b/src/windows/native/common/jni_util_md.c	Sat Oct 17 21:55:25 2015 +0100
@@ -142,6 +142,15 @@
     return (void*)GetModuleHandle(NULL);
 }
 
+int
+getErrorString(int err, char *buf, size_t len)
+{
+    int ret = 0;
+    if (err == 0 || len < 1) return 0;
+    ret = strerror_s(buf, len, err);
+    return ret;
+}
+
 /*
  * Windows symbols can be simple like JNI_OnLoad or __stdcall format
  * like _JNI_OnLoad@8. We need to handle both.
--- a/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c	Wed Oct 14 13:28:29 2015 +0100
+++ b/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c	Sat Oct 17 21:55:25 2015 +0100
@@ -2239,8 +2239,11 @@
 
     optlen = sizeof(optval.i);
     if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
-        char errmsg[255];
-        sprintf(errmsg, "error getting socket option: %s\n", strerror(errno));
+        char tmpbuf[255];
+        int size = 0;
+        char errmsg[255 + 31];
+        getErrorString(errno, tmpbuf, sizeof(tmpbuf));
+        sprintf(errmsg, "error getting socket option: %s", tmpbuf);
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg);
         return NULL;
     }