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