提交 181c000b 编写于 作者: A alanb

6824477: (se) Selector.select fails with IOException: "Invalid argument" if...

6824477: (se) Selector.select fails with IOException: "Invalid argument" if maximum file descriptors is low
Reviewed-by: sherman
上级 27a365b4
......@@ -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,60 +179,34 @@ class DevPollArrayWrapper {
return updated;
}
void updateRegistrations() {
// take snapshot of the updateList size to see if there are
// any registrations to update
int updateSize;
void updateRegistrations() throws IOException {
// Populate pollfd array with updated masks
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 {
synchronized (updateList) {
while (updateList.size() > 0) {
// We have to insert a dummy node in between each
// real update to use POLLREMOVE on the fd first because
// otherwise the changes are simply OR'd together
int index = 0;
Updator u = null;
while ((u = updateList.poll()) != null) {
// First add pollfd struct to clear out this fd
putPollFD(updatePollArray, index, u.fd, POLLREMOVE);
index++;
// Now add pollfd to update this fd, if necessary
if (u.mask != POLLREMOVE) {
putPollFD(updatePollArray, index, u.fd,
(short)u.mask);
index++;
}
// Check against the max allocation 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)
break;
}
// Register the changes with /dev/poll
registerMultiple(wfd, updatePollArray.address(), index);
}
while (updateList.size() > 0) {
// We have to insert a dummy node in between each
// real update to use POLLREMOVE on the fd first because
// otherwise the changes are simply OR'd together
int index = 0;
Updator u = null;
while ((u = updateList.poll()) != null) {
// First add pollfd struct to clear out this fd
putPollFD(updatePollArray, index, u.fd, POLLREMOVE);
index++;
// Now add pollfd to update this fd, if necessary
if (u.mask != POLLREMOVE) {
putPollFD(updatePollArray, index, u.fd, (short)u.mask);
index++;
}
// Check against the max update size; these are
// all we will process. Valid index ranges from 0 to
// (MAX_UPDATE_SIZE - 1) and we can use up to 2 per loop
if (index > MAX_UPDATE_SIZE - 2)
break;
}
} 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.
}
// Register the changes with /dev/poll
registerMultiple(wfd, updatePollArray.address(), index);
}
}
}
......@@ -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);
......
/*
* 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();
}
}
#
# 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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册