United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6823609 (se) Selector.select hangs on Windows under load
JDK-6823609 : (se) Selector.select hangs on Windows under load

Details
Type:
Bug
Submit Date:
2009-03-30
Status:
Closed
Updated Date:
2010-12-11
Project Name:
JDK
Resolved Date:
2010-12-11
Component:
core-libs
OS:
windows_2003,windows
Sub-Component:
java.nio
CPU:
x86,generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
6u10,6u14
Fixed Versions:

Related Reports
Backport:

Sub Tasks

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.
                                     
2009-03-30
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();
+                }
             }
         }
     }
                                     
2009-03-30
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.
                                     
2009-03-30



Hardware and Software, Engineered to Work Together