6824477: (se) Selector.select fails with IOException: "Invalid argument" if maximum file descriptors is low
Reviewed-by: sherman
This commit is contained in:
parent
f83fd900a9
commit
78e9762656
@ -76,20 +76,19 @@ class DevPollArrayWrapper {
|
||||
// Base address of the native pollArray
|
||||
private long pollArrayAddress;
|
||||
|
||||
// Array of pollfd structs used for driver updates
|
||||
private AllocatedNativeObject updatePollArray;
|
||||
|
||||
// Maximum number of POLL_FD structs to update at once
|
||||
private int MAX_UPDATE_SIZE = 10000;
|
||||
private int MAX_UPDATE_SIZE = Math.min(OPEN_MAX, 10000);
|
||||
|
||||
DevPollArrayWrapper() {
|
||||
int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
|
||||
pollArray = new AllocatedNativeObject(allocationSize, true);
|
||||
pollArrayAddress = pollArray.address();
|
||||
allocationSize = MAX_UPDATE_SIZE * SIZE_POLLFD;
|
||||
updatePollArray = new AllocatedNativeObject(allocationSize, true);
|
||||
wfd = init();
|
||||
|
||||
for (int i=0; i<NUM_POLLFDS; i++) {
|
||||
putDescriptor(i, 0);
|
||||
putEventOps(i, 0);
|
||||
putReventOps(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Machinery for remembering fd registration changes
|
||||
@ -129,21 +128,11 @@ class DevPollArrayWrapper {
|
||||
register(wfd, fd0, POLLIN);
|
||||
}
|
||||
|
||||
void putEventOps(int i, int event) {
|
||||
int offset = SIZE_POLLFD * i + EVENT_OFFSET;
|
||||
pollArray.putShort(offset, (short)event);
|
||||
}
|
||||
|
||||
void putReventOps(int i, int revent) {
|
||||
int offset = SIZE_POLLFD * i + REVENT_OFFSET;
|
||||
pollArray.putShort(offset, (short)revent);
|
||||
}
|
||||
|
||||
void putDescriptor(int i, int fd) {
|
||||
int offset = SIZE_POLLFD * i + FD_OFFSET;
|
||||
pollArray.putInt(offset, fd);
|
||||
}
|
||||
|
||||
int getEventOps(int i) {
|
||||
int offset = SIZE_POLLFD * i + EVENT_OFFSET;
|
||||
return pollArray.getShort(offset);
|
||||
@ -174,9 +163,10 @@ class DevPollArrayWrapper {
|
||||
void closeDevPollFD() throws IOException {
|
||||
FileDispatcherImpl.closeIntFD(wfd);
|
||||
pollArray.free();
|
||||
updatePollArray.free();
|
||||
}
|
||||
|
||||
int poll(long timeout) {
|
||||
int poll(long timeout) throws IOException {
|
||||
updateRegistrations();
|
||||
updated = poll0(pollArrayAddress, NUM_POLLFDS, timeout, wfd);
|
||||
for (int i=0; i<updated; i++) {
|
||||
@ -189,25 +179,8 @@ class DevPollArrayWrapper {
|
||||
return updated;
|
||||
}
|
||||
|
||||
void updateRegistrations() {
|
||||
// take snapshot of the updateList size to see if there are
|
||||
// any registrations to update
|
||||
int updateSize;
|
||||
synchronized (updateList) {
|
||||
updateSize = updateList.size();
|
||||
}
|
||||
if (updateSize > 0) {
|
||||
// Construct a pollfd array with updated masks; we may overallocate
|
||||
// by some amount because if the events are already POLLREMOVE
|
||||
// then the second pollfd of that pair will not be needed. The
|
||||
// number of entries is limited to a reasonable number to avoid
|
||||
// allocating a lot of memory.
|
||||
int maxUpdates = Math.min(updateSize * 2, MAX_UPDATE_SIZE);
|
||||
int allocationSize = maxUpdates * SIZE_POLLFD;
|
||||
AllocatedNativeObject updatePollArray =
|
||||
new AllocatedNativeObject(allocationSize, true);
|
||||
|
||||
try {
|
||||
void updateRegistrations() throws IOException {
|
||||
// Populate pollfd array with updated masks
|
||||
synchronized (updateList) {
|
||||
while (updateList.size() > 0) {
|
||||
// We have to insert a dummy node in between each
|
||||
@ -221,29 +194,20 @@ class DevPollArrayWrapper {
|
||||
index++;
|
||||
// Now add pollfd to update this fd, if necessary
|
||||
if (u.mask != POLLREMOVE) {
|
||||
putPollFD(updatePollArray, index, u.fd,
|
||||
(short)u.mask);
|
||||
putPollFD(updatePollArray, index, u.fd, (short)u.mask);
|
||||
index++;
|
||||
}
|
||||
|
||||
// Check against the max allocation size; these are
|
||||
// Check against the max update size; these are
|
||||
// all we will process. Valid index ranges from 0 to
|
||||
// (maxUpdates - 1) and we can use up to 2 per loop
|
||||
if (index > maxUpdates - 2)
|
||||
// (MAX_UPDATE_SIZE - 1) and we can use up to 2 per loop
|
||||
if (index > MAX_UPDATE_SIZE - 2)
|
||||
break;
|
||||
}
|
||||
// Register the changes with /dev/poll
|
||||
registerMultiple(wfd, updatePollArray.address(), index);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Free the native array
|
||||
updatePollArray.free();
|
||||
// BUG: If an exception was thrown then the selector now believes
|
||||
// that the last set of changes was updated but it probably
|
||||
// was not. This should not be a likely occurrence.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void putPollFD(AllocatedNativeObject array, int index, int fd,
|
||||
@ -275,7 +239,8 @@ class DevPollArrayWrapper {
|
||||
|
||||
private native int init();
|
||||
private native void register(int wfd, int fd, int mask);
|
||||
private native void registerMultiple(int wfd, long address, int len);
|
||||
private native void registerMultiple(int wfd, long address, int len)
|
||||
throws IOException;
|
||||
private native int poll0(long pollAddress, int numfds, long timeout,
|
||||
int wfd);
|
||||
private static native void interrupt(int fd);
|
||||
|
38
jdk/test/java/nio/channels/Selector/LotsOfUpdates.java
Normal file
38
jdk/test/java/nio/channels/Selector/LotsOfUpdates.java
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
import java.nio.channels.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LotsOfUpdates {
|
||||
public static void main(String[] args) throws IOException {
|
||||
Selector sel = Selector.open();
|
||||
SocketChannel sc = SocketChannel.open();
|
||||
sc.configureBlocking(false);
|
||||
SelectionKey key = sc.register(sel, 0);
|
||||
for (int i=0; i<50000; i++) {
|
||||
key.interestOps(0);
|
||||
}
|
||||
sel.selectNow();
|
||||
}
|
||||
}
|
49
jdk/test/java/nio/channels/Selector/lots_of_updates.sh
Normal file
49
jdk/test/java/nio/channels/Selector/lots_of_updates.sh
Normal file
@ -0,0 +1,49 @@
|
||||
#
|
||||
# Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
# CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
# have any questions.
|
||||
#
|
||||
|
||||
# @test
|
||||
# @bug 6824477
|
||||
# @summary Selector.select can fail with IOException "Invalid argument" on
|
||||
# Solaris if maximum number of file descriptors is less than 10000
|
||||
# @build LotsOfUpdates
|
||||
# @run shell lots_of_updates.sh
|
||||
|
||||
OS=`uname -s`
|
||||
case "$OS" in
|
||||
Windows_* )
|
||||
echo "ulimit not on Windows"
|
||||
exit 0
|
||||
;;
|
||||
* )
|
||||
CLASSPATH=${TESTCLASSES}:${TESTSRC}
|
||||
;;
|
||||
esac
|
||||
export CLASSPATH
|
||||
|
||||
# hard limit needs to be less than 10000 for this bug
|
||||
NOFILES=`ulimit -n -H`
|
||||
if [ "$NOFILES" = "unlimited" ] || [ $NOFILES -ge 10000 ]; then
|
||||
ulimit -n 2048
|
||||
fi
|
||||
|
||||
${TESTJAVA}/bin/java LotsOfUpdates
|
Loading…
Reference in New Issue
Block a user