8035897: Better memory allocation for file descriptors greater than 1024 on macosx
Reviewed-by: michaelm
--- a/jdk/src/aix/native/java/net/aix_close.c Sun Mar 02 19:21:18 2014 +0000
+++ b/jdk/src/aix/native/java/net/aix_close.c Sun Mar 02 19:27:43 2014 +0000
@@ -61,8 +61,9 @@
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
+#include <sys/poll.h>
-#include <sys/poll.h>
+#include "jni.h"
/*
* Stack allocated by thread when doing blocking operation
@@ -383,7 +384,7 @@
* Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal.
*/
-int NET_Timeout(int s, long timeout) {
+int NET_Timeout(JNIEnv *unused, int s, long timeout) {
long prevtime = 0, newtime;
struct timeval t;
fdEntry_t *fdEntry = getFdEntry(s);
--- a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c Sun Mar 02 19:21:18 2014 +0000
+++ b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c Sun Mar 02 19:27:43 2014 +0000
@@ -501,7 +501,8 @@
return -1;
}
if (timeout) {
- int ret = NET_Timeout(fd, timeout);
+ int ret = NET_Timeout(env, fd, timeout);
+ JNU_CHECK_EXCEPTION_RETURN(env, -1);
if (ret == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"Peek timed out");
@@ -594,7 +595,8 @@
packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID);
if (timeout) {
- int ret = NET_Timeout(fd, timeout);
+ int ret = NET_Timeout(env, fd, timeout);
+ JNU_CHECK_EXCEPTION_RETURN(env, -1);
if (ret == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"Receive timed out");
@@ -802,9 +804,11 @@
retry = JNI_FALSE;
if (timeout) {
- int ret = NET_Timeout(fd, timeout);
+ int ret = NET_Timeout(env, fd, timeout);
if (ret <= 0) {
- if (ret == 0) {
+ if ((*env)->ExceptionCheck(env)) {
+ // fall-through, to potentially free, then return
+ } else if (ret == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"Receive timed out");
} else if (ret == -1) {
--- a/jdk/src/solaris/native/java/net/PlainSocketImpl.c Sun Mar 02 19:21:18 2014 +0000
+++ b/jdk/src/solaris/native/java/net/PlainSocketImpl.c Sun Mar 02 19:27:43 2014 +0000
@@ -670,11 +670,11 @@
/* passing a timeout of 0 to poll will return immediately,
but in the case of ServerSocket 0 means infinite. */
if (timeout <= 0) {
- ret = NET_Timeout(fd, -1);
+ ret = NET_Timeout(env, fd, -1);
} else {
- ret = NET_Timeout(fd, timeout);
+ ret = NET_Timeout(env, fd, timeout);
}
-
+ JNU_CHECK_EXCEPTION(env);
if (ret == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"Accept timed out");
--- a/jdk/src/solaris/native/java/net/SocketInputStream.c Sun Mar 02 19:21:18 2014 +0000
+++ b/jdk/src/solaris/native/java/net/SocketInputStream.c Sun Mar 02 19:27:43 2014 +0000
@@ -100,9 +100,11 @@
}
if (timeout) {
- nread = NET_Timeout(fd, timeout);
+ nread = NET_Timeout(env, fd, timeout);
if (nread <= 0) {
- if (nread == 0) {
+ if ((*env)->ExceptionCheck(env)) {
+ // fall-through, to potentially free, then return
+ } else if (nread == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"Read timed out");
} else if (nread == -1) {
--- a/jdk/src/solaris/native/java/net/bsd_close.c Sun Mar 02 19:21:18 2014 +0000
+++ b/jdk/src/solaris/native/java/net/bsd_close.c Sun Mar 02 19:27:43 2014 +0000
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <sys/param.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
@@ -35,8 +36,9 @@
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
+#include <sys/poll.h>
-#include <sys/poll.h>
+#include "jni_util.h"
/*
* Stack allocated by thread when doing blocking operation
@@ -331,9 +333,13 @@
* Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal.
*/
-int NET_Timeout(int s, long timeout) {
+int NET_Timeout(JNIEnv *env, int s, long timeout) {
long prevtime = 0, newtime;
struct timeval t, *tp = &t;
+ fd_set fds;
+ fd_set* fdsp = NULL;
+ int allocated = 0;
+ threadEntry_t self;
fdEntry_t *fdEntry = getFdEntry(s);
/*
@@ -363,20 +369,30 @@
t.tv_usec = 0;
}
+ if (s < FD_SETSIZE) {
+ fdsp = &fds;
+ FD_ZERO(fdsp);
+ } else {
+ int length = (howmany(s+1, NFDBITS)) * sizeof(int);
+ fdsp = (fd_set *) calloc(1, length);
+ if (fdsp == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "NET_Select native heap allocation failed");
+ return 0;
+ }
+ allocated = 1;
+ }
+ FD_SET(s, fdsp);
+
for(;;) {
- fd_set rfds;
int rv;
- threadEntry_t self;
/*
* call select on the fd. If interrupted by our wakeup signal
* errno will be set to EBADF.
*/
- FD_ZERO(&rfds);
- FD_SET(s, &rfds);
startOp(fdEntry, &self);
- rv = select(s+1, &rfds, 0, 0, tp);
+ rv = select(s+1, fdsp, 0, 0, tp);
endOp(fdEntry, &self);
/*
@@ -390,6 +406,8 @@
newtime = now.tv_sec * 1000 + now.tv_usec / 1000;
timeout -= newtime - prevtime;
if (timeout <= 0) {
+ if (allocated != 0)
+ free(fdsp);
return 0;
}
prevtime = newtime;
@@ -397,6 +415,8 @@
t.tv_usec = (timeout % 1000) * 1000;
}
} else {
+ if (allocated != 0)
+ free(fdsp);
return rv;
}
--- a/jdk/src/solaris/native/java/net/linux_close.c Sun Mar 02 19:21:18 2014 +0000
+++ b/jdk/src/solaris/native/java/net/linux_close.c Sun Mar 02 19:27:43 2014 +0000
@@ -34,8 +34,9 @@
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>
+#include <sys/poll.h>
-#include <sys/poll.h>
+#include "jni.h"
/*
* Stack allocated by thread when doing blocking operation
@@ -313,7 +314,7 @@
* Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal.
*/
-int NET_Timeout(int s, long timeout) {
+int NET_Timeout(JNIEnv *unused, int s, long timeout) {
long prevtime = 0, newtime;
struct timeval t;
fdEntry_t *fdEntry = getFdEntry(s);
--- a/jdk/src/solaris/native/java/net/net_util_md.h Sun Mar 02 19:21:18 2014 +0000
+++ b/jdk/src/solaris/native/java/net/net_util_md.h Sun Mar 02 19:27:43 2014 +0000
@@ -34,7 +34,7 @@
#include <sys/poll.h>
-int NET_Timeout(int s, long timeout);
+int NET_Timeout(JNIEnv *env, int s, long timeout);
int NET_Read(int s, void* buf, size_t len);
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen);
--- a/jdk/src/solaris/native/java/net/solaris_close.c Sun Mar 02 19:21:18 2014 +0000
+++ b/jdk/src/solaris/native/java/net/solaris_close.c Sun Mar 02 19:27:43 2014 +0000
@@ -28,6 +28,8 @@
#include <stropts.h>
#include <unistd.h>
+#include "jni.h"
+
/* Support for restartable system calls on Solaris. */
#define RESTARTABLE_RETURN_INT(_cmd) do { \
@@ -86,7 +88,7 @@
RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
}
-int NET_Timeout(int s, long timeout) {
+int NET_Timeout(JNIEnv *unused, int s, long timeout) {
int result;
struct timeval t;
long prevtime, newtime;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/ServerSocket/AnotherSelectFdsLimit.java Sun Mar 02 19:27:43 2014 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8035897
+ * @summary FD_SETSIZE should be set on macosx
+ * @run main/othervm AnotherSelectFdsLimit 1023
+ * @run main/othervm AnotherSelectFdsLimit 1024
+ * @run main/othervm AnotherSelectFdsLimit 1025
+ * @run main/othervm AnotherSelectFdsLimit 1600
+ */
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class AnotherSelectFdsLimit {
+ static final int DEFAULT_FDS_TO_USE = 1600;
+
+ public static void main(String [] args) throws Exception {
+ if (!System.getProperty("os.name").contains("OS X")) {
+ System.out.println("Test only run on MAC. Exiting.");
+ return;
+ }
+
+ int fdsToUse = DEFAULT_FDS_TO_USE;
+ if (args.length == 1)
+ fdsToUse = Integer.parseInt(args[0]);
+
+ System.out.println("Using " + fdsToUse + " fds.");
+
+ List<Thread> threads = new ArrayList<>();
+ for (int i=0; i<fdsToUse; i++)
+ threads.add(new WorkerThread());
+
+ for (Thread t : threads)
+ t.start();
+
+ for (Thread t : threads)
+ t.join();
+ }
+
+ static class WorkerThread extends Thread {
+ public void run() {
+ try (ServerSocket ss = new ServerSocket(0)) {
+ ss.setSoTimeout(2000);
+ ss.accept();
+ } catch (SocketTimeoutException x) {
+ // expected
+ } catch (IOException x) {
+ throw new java.io.UncheckedIOException(x);
+ }
+ }
+ }
+}