<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Hi there,</div><div><br></div><div>this is my first bug-report here so bear with me if something is missing ;)</div><div><br></div><div>During testing netty.io with many concurrent connections one of our users reported a NullPointerException which was thrown by sun.nio.ch.EPollArrayWrapper.setUpdateEvents(...). This was observed as soon as the concurrent connection count > 64 * 1024. After more investigating I was able to find the bug in EPollArrayWrapper.setUpdateEvents(...), which is a regression introduced by the following change:</div><div><br></div><div><a href="http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/rev/017bd924a3c8">http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/rev/017bd924a3c8</a></div><div><br></div><div>The problem here is that eventsHigh.get(key) will be called once the fd is > 64 * 1024. This may return "null" which is compared to KILLED (which is of type byte) and so may throw a NPE because the compare tries to unbox the return value (which is of type Byte). The regression is present in lastest openjdk8 and in openjdk7u40 and later. It seems to also affects oracle jdk 7u40. All OS'es that use epoll are affected, in my case linux (ubuntu).</div><div><br></div><div>Attached you find the proposed fix for openjdk8 and openjdk7 and a reproducer which can be used. The fix does two things:</div><div>* Eliminate the access to the eventsHigh Map if "force" is true.</div><div>* Check for null before try to compare the stored events value</div><div><br></div><div><br></div><div>Reproducer:</div><div>The reproducer will bind a server to the specified port and just accept new connections. The clients will connect to the server until 80 * 1024 connections are reached, and then go to sleep. When you use the reproducer without the attached fix the server will fail with:</div><div><br></div><div>Exception in thread "main" java.lang.NullPointerException</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>at sun.nio.ch.EPollArrayWrapper.setUpdateEvents(EPollArrayWrapper.java:178)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>at sun.nio.ch.EPollArrayWrapper.add(EPollArrayWrapper.java:227)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>at sun.nio.ch.EPollSelectorImpl.implRegister(EPollSelectorImpl.java:164)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>at sun.nio.ch.SelectorImpl.register(SelectorImpl.java:132)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>at java.nio.channels.spi.AbstractSelectableChannel.register(AbstractSelectableChannel.java:212)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>at java.nio.channels.SelectableChannel.register(SelectableChannel.java:280)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>at BugReproducer.main(BugReproducer.java:39)</div><div><br></div><div>Once the fix is applied no Exception is thrown anymore. </div><div><br></div><div>To run the reproducer you may need to update the localport range. For this use the following command:</div><div># sudo sysctl -w net.ipv4.ip_local_port_range="1024 64000"</div><div><br></div><div>Also you may need to increate ulimit to something big enough. I'm using 1048576 here to test it.</div><div><br></div><div>You need two interfaces if you not have more then one you can use a virtual interface. So if you have for example eth0 with the ipaddress 10.0.0.9 you can use something like the following to setup a virtual interface:</div><div># sudo ifconfig eth0:1 10.0.0.10 broadcast 255.255.255.0</div><div><br></div><div>Compile the reproducer classes, which you should put in somedir (here we call it /tmp/niobug/)</div><div># cd /tmp/niobug/</div><div># javac -cp . Bug*.class</div><div><br></div><div>After the classes are compiled you will need 3 terminals. One for the server and the other 2 to run the clients.</div><div>First Terminal:</div><div># java -Djava.net.preferIPv4Stack=true -cp . BugReproducer 8080</div><div><br></div><div>Second Terminal:</div><div># java -Djava.net.preferIPv4Stack=true -cp . BugReproducerClient 10.0.0.9 8080</div><div><br></div><div>Third Terminal:</div><div># java -Djava.net.preferIPv4Stack=true -cp . BugReproducerClient 10.0.0.10 8080</div><div><br></div><div>You will see the concurrent connection count in the First Terminal.</div><div><br></div><div><br></div><div><br></div></body></html>