Fixes #335836 (Race when updating SelectChannelEndPoint._dispatched)

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2714 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Simone Bordet 2011-01-31 12:28:38 +00:00
parent caff41bebb
commit 813d652e41
2 changed files with 45 additions and 42 deletions

View File

@ -31,6 +31,7 @@ jetty-7.3.0-SNAPSHOT
+ 335361 Fixed 'jetty.sh check' to show current PID when JETTY_PID env. variable is set
+ 335641 Cleaned up dispatch handling to avoid key.interestOps==0 when undispatched
+ 335681 Improve ChannelEndPoint.close() to avoid spinning
+ 335836 Race when updating SelectChannelEndPoint._dispatched
jetty-7.2.2.v20101205 5 December 2010
+ JETTY-1308 327109 (re)fixed AJP handling of empty packets

View File

@ -4,11 +4,11 @@
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.io.nio;
@ -43,8 +43,8 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
private volatile Connection _connection;
private boolean _dispatched = false;
private boolean _redispatched = false;
private volatile boolean _writable = true;
private volatile boolean _writable = true;
private SelectionKey _key;
private int _interestOps;
private boolean _readBlocked;
@ -62,11 +62,11 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
_selectSet = selectSet;
_dispatched = false;
_redispatched = false;
_open=true;
_open=true;
_key = key;
_connection = _manager.newConnection(channel,this);
scheduleIdle();
}
@ -75,16 +75,16 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
throws IOException
{
super(channel);
_manager = selectSet.getManager();
_selectSet = selectSet;
_dispatched = false;
_redispatched = false;
_open=true;
_open=true;
_key = key;
_connection = _manager.newConnection(channel,this);
scheduleIdle();
}
/* ------------------------------------------------------------ */
@ -95,19 +95,19 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
return _key;
}
}
/* ------------------------------------------------------------ */
public SelectorManager getSelectManager()
{
return _manager;
}
/* ------------------------------------------------------------ */
public Connection getConnection()
{
return _connection;
}
/* ------------------------------------------------------------ */
public void setConnection(Connection connection)
{
@ -118,9 +118,9 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
/* ------------------------------------------------------------ */
/** Called by selectSet to schedule handling
*
*
*/
public void schedule()
public void schedule()
{
synchronized (this)
{
@ -132,7 +132,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
this.notifyAll();
return;
}
// If there are threads dispatched reading and writing
if (_readBlocked || _writeBlocked)
{
@ -144,7 +144,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
// wake them up is as good as a dispatched.
this.notifyAll();
// we are not interested in further selecting
if (_dispatched)
_key.interestOps(0);
@ -179,9 +179,9 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
}
}
/* ------------------------------------------------------------ */
public void dispatch()
public void dispatch()
{
synchronized(this)
{
@ -191,9 +191,11 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
else
{
_dispatched = _manager.dispatch(_handler);
if(!_dispatched)
_dispatched = true;
boolean dispatched = _manager.dispatch(_handler);
if(!dispatched)
{
_dispatched = false;
Log.warn("Dispatched Failed!");
updateKey();
}
@ -203,12 +205,12 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
/* ------------------------------------------------------------ */
/**
* Called when a dispatched thread is no longer handling the endpoint.
* Called when a dispatched thread is no longer handling the endpoint.
* The selection key operations are updated.
* @return If false is returned, the endpoint has been redispatched and
* @return If false is returned, the endpoint has been redispatched and
* thread must keep handling the endpoint.
*/
private boolean undispatch()
protected boolean undispatch()
{
synchronized (this)
{
@ -234,7 +236,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
{
_idleTimestamp=0;
}
/* ------------------------------------------------------------ */
public void checkIdleTimestamp(long now)
{
@ -300,7 +302,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
return !(_dispatched || getConnection().isSuspended());
}
}
/* ------------------------------------------------------------ */
/*
* Allows thread to block waiting for further events.
@ -312,7 +314,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
{
long start=_selectSet.getNow();
try
{
{
_readBlocked=true;
while (isOpen() && _readBlocked)
{
@ -350,7 +352,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
{
long start=_selectSet.getNow();
try
{
{
_writeBlocked=true;
while (isOpen() && _writeBlocked)
{
@ -384,14 +386,14 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
{
_writable=writable;
}
/* ------------------------------------------------------------ */
public void scheduleWrite()
{
_writable=false;
updateKey();
}
/* ------------------------------------------------------------ */
/**
* Updates selection key. Adds operations types to the selection key as needed. No operations
@ -405,8 +407,8 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
int ops=-1;
if (getChannel().isOpen())
{
_interestOps =
((!_dispatched || _readBlocked) ? SelectionKey.OP_READ : 0)
_interestOps =
((!_dispatched || _readBlocked) ? SelectionKey.OP_READ : 0)
| ((!_writable || _writeBlocked) ? SelectionKey.OP_WRITE : 0);
try
{
@ -425,7 +427,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
_selectSet.addChange(this);
_selectSet.wakeup();
}
/* ------------------------------------------------------------ */
/**
* Synchronize the interestOps with the actual key. Call is scheduled by a call to updateKey
@ -443,7 +445,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
SelectableChannel sc = (SelectableChannel)getChannel();
if (sc.isRegistered())
{
updateKey();
updateKey();
}
else
{
@ -482,11 +484,11 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
_key=null;
}
}
else
else
{
if (_key!=null && _key.isValid())
_key.cancel();
_key.cancel();
cancelIdle();
if (_open)
{
@ -499,9 +501,9 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
/* ------------------------------------------------------------ */
/*
/*
*/
private void handle()
protected void handle()
{
boolean dispatched=true;
try
@ -514,7 +516,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
{
final Connection next = _connection.handle();
if (next!=_connection)
{
{
_connection=next;
continue;
}
@ -575,20 +577,20 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
catch (IOException e)
{
Log.ignore(e);
}
}
finally
{
updateKey();
}
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
synchronized(this)
{
return "SCEP@" + hashCode() + "\t[d=" + _dispatched + ",io=" + _interestOps+
return "SCEP@" + hashCode() + " [d=" + _dispatched + ",io=" + _interestOps+
",w=" + _writable + ",rb=" + _readBlocked + ",wb=" + _writeBlocked + "]";
}
}