提交 b905eaa5 编写于 作者: A alanb

6823609: (se) Selector.select hangs on Windows under load

Reviewed-by: sherman
上级 181c000b
...@@ -34,7 +34,6 @@ import java.nio.channels.Selector; ...@@ -34,7 +34,6 @@ import java.nio.channels.Selector;
import java.nio.channels.ClosedSelectorException; import java.nio.channels.ClosedSelectorException;
import java.nio.channels.Pipe; import java.nio.channels.Pipe;
import java.nio.channels.SelectableChannel; import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -72,7 +71,7 @@ final class WindowsSelectorImpl extends SelectorImpl { ...@@ -72,7 +71,7 @@ final class WindowsSelectorImpl extends SelectorImpl {
private int threadsCount = 0; private int threadsCount = 0;
// A list of helper threads for select. // A list of helper threads for select.
private final List<Thread> threads = new ArrayList<Thread>(); private final List<SelectThread> threads = new ArrayList<SelectThread>();
//Pipe used as a wakeup object. //Pipe used as a wakeup object.
private final Pipe wakeupPipe; private final Pipe wakeupPipe;
...@@ -201,7 +200,7 @@ final class WindowsSelectorImpl extends SelectorImpl { ...@@ -201,7 +200,7 @@ final class WindowsSelectorImpl extends SelectorImpl {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
} }
if (thread.index >= threads.size()) { // redundant thread if (thread.isZombie()) { // redundant thread
return true; // will cause run() to exit. return true; // will cause run() to exit.
} else { } else {
thread.lastRun = runsCounter; // update lastRun thread.lastRun = runsCounter; // update lastRun
...@@ -388,9 +387,10 @@ final class WindowsSelectorImpl extends SelectorImpl { ...@@ -388,9 +387,10 @@ final class WindowsSelectorImpl extends SelectorImpl {
// Represents a helper thread used for select. // Represents a helper thread used for select.
private final class SelectThread extends Thread { private final class SelectThread extends Thread {
private int index; // index of this thread private final int index; // index of this thread
SubSelector subSelector; final SubSelector subSelector;
private long lastRun = 0; // last run number private long lastRun = 0; // last run number
private volatile boolean zombie;
// Creates a new thread // Creates a new thread
private SelectThread(int i) { private SelectThread(int i) {
this.index = i; this.index = i;
...@@ -398,6 +398,12 @@ final class WindowsSelectorImpl extends SelectorImpl { ...@@ -398,6 +398,12 @@ final class WindowsSelectorImpl extends SelectorImpl {
//make sure we wait for next round of poll //make sure we wait for next round of poll
this.lastRun = startLock.runsCounter; this.lastRun = startLock.runsCounter;
} }
void makeZombie() {
zombie = true;
}
boolean isZombie() {
return zombie;
}
public void run() { public void run() {
while (true) { // poll loop while (true) { // poll loop
// wait for the start of poll. If this thread has become // wait for the start of poll. If this thread has become
...@@ -432,7 +438,7 @@ final class WindowsSelectorImpl extends SelectorImpl { ...@@ -432,7 +438,7 @@ final class WindowsSelectorImpl extends SelectorImpl {
} else if (threadsCount < threads.size()) { } else if (threadsCount < threads.size()) {
// Some threads become redundant. Remove them from the threads List. // Some threads become redundant. Remove them from the threads List.
for (int i = threads.size() - 1 ; i >= threadsCount; i--) for (int i = threads.size() - 1 ; i >= threadsCount; i--)
threads.remove(i); threads.remove(i).makeZombie();
} }
} }
...@@ -468,10 +474,9 @@ final class WindowsSelectorImpl extends SelectorImpl { ...@@ -468,10 +474,9 @@ final class WindowsSelectorImpl extends SelectorImpl {
updateCount++; updateCount++;
int numKeysUpdated = 0; int numKeysUpdated = 0;
numKeysUpdated += subSelector.processSelectedKeys(updateCount); numKeysUpdated += subSelector.processSelectedKeys(updateCount);
Iterator it = threads.iterator(); for (SelectThread t: threads) {
while (it.hasNext()) numKeysUpdated += t.subSelector.processSelectedKeys(updateCount);
numKeysUpdated += ((SelectThread)it.next()).subSelector. }
processSelectedKeys(updateCount);
return numKeysUpdated; return numKeysUpdated;
} }
...@@ -495,13 +500,13 @@ final class WindowsSelectorImpl extends SelectorImpl { ...@@ -495,13 +500,13 @@ final class WindowsSelectorImpl extends SelectorImpl {
} }
pollWrapper.free(); pollWrapper.free();
pollWrapper = null; pollWrapper = null;
selectedKeys = null; selectedKeys = null;
channelArray = null; channelArray = null;
threads.clear(); // Make all remaining helper threads exit
// Call startThreads. All remaining helper threads now exit, for (SelectThread t: threads)
// since threads.size() = 0; t.makeZombie();
startLock.startThreads(); startLock.startThreads();
} }
} }
} }
} }
......
/*
* 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 6823609
* @summary Selector.select can hangs on Windows for cases where a helper thread
* becomes redudant but a new helper is immediately needed.
*/
import java.nio.channels.*;
import java.io.IOException;
public class HelperSlowToDie {
private static final int CHANNELS_PER_THREAD = 1023;
private static volatile boolean done;
public static void main(String[] args) throws IOException {
Selector sel = Selector.open();
// register channels
SocketChannel[] channels = new SocketChannel[CHANNELS_PER_THREAD];
for (int i=0; i<CHANNELS_PER_THREAD; i++) {
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
sc.register(sel, SelectionKey.OP_CONNECT);
channels[i] = sc;
}
sel.selectNow();
// Start threads to swamp all cores but one. This improves the chances
// of duplicating the bug.
Runnable busy = new Runnable() {
public void run() {
while (!done) ; // no nothing
}
};
int ncores = Runtime.getRuntime().availableProcessors();
for (int i=0; i<ncores-1; i++)
new Thread(busy).start();
// Loop changing the number of channels from 1023 to 1024 and back.
for (int i=0; i<1000; i++) {
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(false);
sc.register(sel, SelectionKey.OP_CONNECT);
sel.selectNow(); // cause helper to spin up
sc.close();
sel.selectNow(); // cause helper to retire
}
// terminate busy threads
done = true;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册