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
This commit is contained in:
Greg Wilkins 2011-05-18 21:59:02 +00:00
parent 8f257c6fd8
commit eb17ca8cbf
3 changed files with 87 additions and 45 deletions

View File

@ -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;
}
}

View File

@ -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();
}
}
/* ------------------------------------------------------------ */

View File

@ -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)