From eb17ca8cbf4519f7be5d0b14b5890c0a475d7113 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 18 May 2011 21:59:02 +0000 Subject: [PATCH] JETTY-1342 Recreate selector if wakeup throws JVM bug git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@3212 7e9141cc-0065-0410-87d8-b60c137991c4 --- .../jetty/io/nio/SelectChannelEndPoint.java | 12 +- .../eclipse/jetty/io/nio/SelectorManager.java | 108 ++++++++++++------ .../java/org/eclipse/jetty/server/Server.java | 12 +- 3 files changed, 87 insertions(+), 45 deletions(-) diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java index 3ea36ce1f44..6fb4b47bf14 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java @@ -316,7 +316,8 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo { synchronized (this) { - long start=_selectSet.getNow(); + long now=_selectSet.getNow(); + long end=now+timeoutMs; try { _readBlocked=true; @@ -325,15 +326,18 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo try { updateKey(); - this.wait(timeoutMs); + this.wait(end-now); } catch (InterruptedException e) { Log.warn(e); } + finally + { + now=_selectSet.getNow(); + } - timeoutMs -= _selectSet.getNow()-start; - if (_readBlocked && timeoutMs<=0) + if (_readBlocked && now>=end) return false; } } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectorManager.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectorManager.java index 14631202fdb..23390b84453 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectorManager.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectorManager.java @@ -15,6 +15,7 @@ package org.eclipse.jetty.io.nio; import java.io.IOException; import java.nio.channels.CancelledKeyException; +import java.nio.channels.Channel; import java.nio.channels.ClosedSelectorException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; @@ -29,6 +30,8 @@ import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import javax.management.RuntimeErrorException; + import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; @@ -389,12 +392,16 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa int changes=_changes.size(); while (changes-->0 && (change=_changes.poll())!=null) { + Channel ch=null; + SelectionKey key=null; + try { if (change instanceof EndPoint) { // Update the operations for a key. SelectChannelEndPoint endpoint = (SelectChannelEndPoint)change; + ch=endpoint.getChannel(); endpoint.doUpdateKey(); } else if (change instanceof ChannelAndAttachment) @@ -402,25 +409,27 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa // finish accepting/connecting this connection final ChannelAndAttachment asc = (ChannelAndAttachment)change; final SelectableChannel channel=asc._channel; + ch=channel; final Object att = asc._attachment; if ((channel instanceof SocketChannel) && ((SocketChannel)channel).isConnected()) { - SelectionKey key = channel.register(selector,SelectionKey.OP_READ,att); + key = channel.register(selector,SelectionKey.OP_READ,att); SelectChannelEndPoint endpoint = createEndPoint((SocketChannel)channel,key); key.attach(endpoint); endpoint.schedule(); } else if (channel.isOpen()) { - channel.register(selector,SelectionKey.OP_CONNECT,att); + key = channel.register(selector,SelectionKey.OP_CONNECT,att); } } else if (change instanceof SocketChannel) { // Newly registered channel final SocketChannel channel=(SocketChannel)change; - SelectionKey key = channel.register(selector,SelectionKey.OP_READ,null); + ch=channel; + key = channel.register(selector,SelectionKey.OP_READ,null); SelectChannelEndPoint endpoint = createEndPoint(channel,key); key.attach(endpoint); endpoint.schedule(); @@ -432,19 +441,27 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa else throw new IllegalArgumentException(change.toString()); } - catch (Exception e) - { - if (isRunning()) - Log.warn(e); - else - Log.debug(e); - } - catch (Error e) + catch (Throwable e) { + if (e instanceof ThreadDeath) + throw (ThreadDeath)e; + if (isRunning()) Log.warn(e); else Log.debug(e); + + if(ch!=null && key==null) + { + try + { + ch.close(); + } + catch(IOException e2) + { + Log.debug(e2); + } + } } } @@ -689,27 +706,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa } else if (_jvmBug==__JVMBUG_THRESHHOLD) { - synchronized (this) - { - // BLOODY SUN BUG !!! Try refreshing the entire selector. - final Selector new_selector = Selector.open(); - for (SelectionKey k: selector.keys()) - { - if (!k.isValid() || k.interestOps()==0) - continue; - - final SelectableChannel channel = k.channel(); - final Object attachment = k.attachment(); - - if (attachment==null) - addChange(channel); - else - addChange(channel,attachment); - } - _selector.close(); - _selector=new_selector; - return; - } + renewSelector(); } else if (_jvmBug%32==31) // heuristic attempt to cancel key 31,63,95,... loops { @@ -765,6 +762,40 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa } } + /* ------------------------------------------------------------ */ + private void renewSelector() + { + try + { + synchronized (this) + { + Selector selector=_selector; + if (selector==null) + return; + final Selector new_selector = Selector.open(); + for (SelectionKey k: selector.keys()) + { + if (!k.isValid() || k.interestOps()==0) + continue; + + final SelectableChannel channel = k.channel(); + final Object attachment = k.attachment(); + + if (attachment==null) + addChange(channel); + else + addChange(channel,attachment); + } + _selector.close(); + _selector=new_selector; + } + } + catch(IOException e) + { + throw new RuntimeException("recreating selector",e); + } + } + /* ------------------------------------------------------------ */ public SelectorManager getManager() { @@ -800,9 +831,16 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa /* ------------------------------------------------------------ */ public void wakeup() { - Selector selector = _selector; - if (selector!=null) - selector.wakeup(); + try + { + Selector selector = _selector; + if (selector!=null) + selector.wakeup(); + } + catch(Exception e) + { + renewSelector(); + } } /* ------------------------------------------------------------ */ diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 1830a9e2ec8..55d57c7920d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -50,15 +50,15 @@ import org.eclipse.jetty.util.thread.ThreadPool; */ public class Server extends HandlerWrapper implements Attributes { - private static final String _version; + private static final String __version; static { if (Server.class.getPackage()!=null && "Eclipse.org - Jetty".equals(Server.class.getPackage().getImplementationVendor()) && Server.class.getPackage().getImplementationVersion()!=null) - _version=Server.class.getPackage().getImplementationVersion(); + __version=Server.class.getPackage().getImplementationVersion(); else - _version=System.getProperty("jetty.version","7.x.y-SNAPSHOT"); + __version=System.getProperty("jetty.version","7.x.y-SNAPSHOT"); } private final Container _container=new Container(); @@ -112,7 +112,7 @@ public class Server extends HandlerWrapper implements Attributes /* ------------------------------------------------------------ */ public static String getVersion() { - return _version; + return __version; } /* ------------------------------------------------------------ */ @@ -246,8 +246,8 @@ public class Server extends HandlerWrapper implements Attributes if (getStopAtShutdown()) ShutdownThread.register(this); - Log.info("jetty-"+_version); - HttpGenerator.setServerVersion(_version); + Log.info("jetty-"+__version); + HttpGenerator.setServerVersion(__version); MultiException mex=new MultiException(); if (_threadPool==null)