JDK-6823609 : (se) Selector.select hangs on Windows under load
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 6u10,6u14
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: windows,windows_2003
  • CPU: generic,x86
  • Submitted: 2009-03-30
  • Updated: 2010-12-11
  • Resolved: 2010-12-11
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u18Fixed 7 b55Fixed
Description
It looks like thread synchronization issue in the Windows Selector implementation could lead application to hang.
The problem was discovered when running  SPECjAppServer with OC4J Application Server.

Comments
SUGGESTED FIX See WindowsSelectorImpl.patch attached.
30-03-2009

SUGGESTED FIX diff -r 52bdf8cec41d src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java --- a/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Tue Mar 24 14:10:38 2009 +0000 +++ b/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Mon Mar 30 13:08:45 2009 +0100 @@ -34,7 +34,6 @@ import java.nio.channels.ClosedSelectorE import java.nio.channels.ClosedSelectorException; import java.nio.channels.Pipe; import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; import java.io.IOException; import java.util.List; import java.util.ArrayList; @@ -72,7 +71,7 @@ final class WindowsSelectorImpl extends private int threadsCount = 0; // 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. private final Pipe wakeupPipe; @@ -201,7 +200,7 @@ final class WindowsSelectorImpl extends Thread.currentThread().interrupt(); } } - if (thread.index >= threads.size()) { // redundant thread + if (thread.isZombie()) { // redundant thread return true; // will cause run() to exit. } else { thread.lastRun = runsCounter; // update lastRun @@ -388,15 +387,22 @@ final class WindowsSelectorImpl extends // Represents a helper thread used for select. private final class SelectThread extends Thread { - private int index; // index of this thread - SubSelector subSelector; + private final int index; // index of this thread + final SubSelector subSelector; private long lastRun = 0; // last run number + private volatile boolean zombie; // Creates a new thread private SelectThread(int i) { this.index = i; this.subSelector = new SubSelector(i); //make sure we wait for next round of poll this.lastRun = startLock.runsCounter; + } + void makeZombie() { + zombie = true; + } + boolean isZombie() { + return zombie; } public void run() { while (true) { // poll loop @@ -432,7 +438,7 @@ final class WindowsSelectorImpl extends } else if (threadsCount < threads.size()) { // Some threads become redundant. Remove them from the threads List. for (int i = threads.size() - 1 ; i >= threadsCount; i--) - threads.remove(i); + threads.remove(i).makeZombie(); } } @@ -468,10 +474,9 @@ final class WindowsSelectorImpl extends updateCount++; int numKeysUpdated = 0; numKeysUpdated += subSelector.processSelectedKeys(updateCount); - Iterator it = threads.iterator(); - while (it.hasNext()) - numKeysUpdated += ((SelectThread)it.next()).subSelector. - processSelectedKeys(updateCount); + for (SelectThread t: threads) { + numKeysUpdated += t.subSelector.processSelectedKeys(updateCount); + } return numKeysUpdated; } @@ -495,13 +500,13 @@ final class WindowsSelectorImpl extends } pollWrapper.free(); pollWrapper = null; - selectedKeys = null; - channelArray = null; - threads.clear(); - // Call startThreads. All remaining helper threads now exit, - // since threads.size() = 0; - startLock.startThreads(); - } + selectedKeys = null; + channelArray = null; + // Make all remaining helper threads exit + for (SelectThread t: threads) + t.makeZombie(); + startLock.startThreads(); + } } } }
30-03-2009

EVALUATION The issue here is that a redundant thread can corrupt the the count of the number of threads waiting to finish. This can arise when the number of threads increases immediately after a decrease.
30-03-2009