From 0a97b66b141951a4b87d10cea525a93bfa3804d1 Mon Sep 17 00:00:00 2001 From: cao tianze Date: Tue, 20 Dec 2016 01:15:32 +0800 Subject: [PATCH 1/3] delete redundant addBean(serverChannel) invoke Signed-off-by: cao tianze --- .../src/main/java/org/eclipse/jetty/server/ServerConnector.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java index 3c0c62e2119..41d5e4828d0 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java @@ -319,8 +319,6 @@ public class ServerConnector extends AbstractNetworkConnector _localPort = serverChannel.socket().getLocalPort(); if (_localPort <= 0) throw new IOException("Server channel not bound"); - - addBean(serverChannel); } serverChannel.configureBlocking(true); From 8ecfbab79f1fd8dba6bf107ddd7d359475b63f8d Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 8 Feb 2017 11:39:03 +1100 Subject: [PATCH 2/3] Issue #1047 - ReadPendingException and then thread death. Alternate fix. Tracking needed vs interested state within HttpChannelState rather that ignoring duplicate interest registrations. --- .../jetty/server/HttpChannelState.java | 62 ++++++++++++++----- .../eclipse/jetty/server/HttpConnection.java | 2 +- .../jetty/http/client/AsyncIOServletTest.java | 2 +- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java index 5ff9e4f0304..35cf0e40fe7 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java @@ -92,6 +92,23 @@ public class HttpChannelState ERRORED // The error has been processed } + public enum Interest + { + NONE(false), + NEEDED(true), + INTERESTED(true); + + final boolean _interested; + boolean isInterested() { return _interested;} + boolean notInterested() { return !_interested;} + + Interest(boolean interest) + { + _interested = interest; + } + + } + private final boolean DEBUG=LOG.isDebugEnabled(); private final Locker _locker=new Locker(); private final HttpChannel _channel; @@ -101,7 +118,7 @@ public class HttpChannelState private Async _async; private boolean _initial; private boolean _asyncReadPossible; - private boolean _asyncReadUnready; + private Interest _asyncRead=Interest.NONE; private boolean _asyncWrite; // TODO refactor same as read private long _timeoutMs=DEFAULT_TIMEOUT; private AsyncContextEvent _event; @@ -161,9 +178,15 @@ public class HttpChannelState { try(Locker.Lock lock= _locker.lock()) { - return String.format("%s@%x{s=%s a=%s i=%b r=%s w=%b}",getClass().getSimpleName(),hashCode(),_state,_async,_initial, - _asyncReadPossible?(_asyncReadUnready?"PU":"P!U"):(_asyncReadUnready?"!PU":"!P!U"), - _asyncWrite); + return String.format("%s@%x{s=%s a=%s i=%b r=%s/%s w=%b}", + getClass().getSimpleName(), + hashCode(), + _state, + _async, + _initial, + _asyncRead, + _asyncReadPossible, + _asyncWrite); } } @@ -201,10 +224,10 @@ public class HttpChannelState return Action.TERMINATED; case ASYNC_WOKEN: - if (_asyncReadPossible) + if (_asyncRead.isInterested() && _asyncReadPossible) { _state=State.ASYNC_IO; - _asyncReadUnready=false; + _asyncRead=Interest.NONE; return Action.READ_CALLBACK; } @@ -402,10 +425,10 @@ public class HttpChannelState break; case STARTED: - if (_asyncReadUnready && _asyncReadPossible) + if (_asyncRead.isInterested() && _asyncReadPossible) { _state=State.ASYNC_IO; - _asyncReadUnready=false; + _asyncRead=Interest.NONE; action = Action.READ_CALLBACK; } else if (_asyncWrite) // TODO refactor same as read @@ -418,8 +441,11 @@ public class HttpChannelState { _state=State.ASYNC_WAIT; action=Action.WAIT; - if (_asyncReadUnready) + if (_asyncRead==Interest.NEEDED) + { + _asyncRead=Interest.INTERESTED; read_interested=true; + } Scheduler scheduler=_channel.getScheduler(); if (scheduler!=null && _timeoutMs>0) _event.setTimeoutTask(scheduler.schedule(_event,_timeoutMs,TimeUnit.MILLISECONDS)); @@ -754,7 +780,8 @@ public class HttpChannelState _state=State.IDLE; _async=Async.NOT_ASYNC; _initial=true; - _asyncReadPossible=_asyncReadUnready=false; + _asyncReadPossible=false; + _asyncRead=Interest.NONE; _asyncWrite=false; _timeoutMs=DEFAULT_TIMEOUT; _event=null; @@ -778,7 +805,8 @@ public class HttpChannelState _state=State.UPGRADED; _async=Async.NOT_ASYNC; _initial=true; - _asyncReadPossible=_asyncReadUnready=false; + _asyncReadPossible=false; + _asyncRead=Interest.NONE; _asyncWrite=false; _timeoutMs=DEFAULT_TIMEOUT; _event=null; @@ -958,12 +986,16 @@ public class HttpChannelState try(Locker.Lock lock= _locker.lock()) { // We were already unready, this is not a state change, so do nothing - if (!_asyncReadUnready) + if (_asyncRead!=Interest.INTERESTED) { - _asyncReadUnready=true; _asyncReadPossible=false; // Assumes this has been checked in isReady() with lock held if (_state==State.ASYNC_WAIT) + { interested=true; + _asyncRead=Interest.INTERESTED; + } + else + _asyncRead=Interest.NEEDED; } } @@ -984,7 +1016,7 @@ public class HttpChannelState try(Locker.Lock lock= _locker.lock()) { _asyncReadPossible=true; - if (_state==State.ASYNC_WAIT && _asyncReadUnready) + if (_state==State.ASYNC_WAIT && _asyncRead.isInterested()) { woken=true; _state=State.ASYNC_WOKEN; @@ -1005,7 +1037,7 @@ public class HttpChannelState boolean woken=false; try(Locker.Lock lock= _locker.lock()) { - _asyncReadUnready=true; + _asyncRead=Interest.INTERESTED; _asyncReadPossible=true; if (_state==State.ASYNC_WAIT) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index 6a2cc44aa3d..f6eb012d268 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -546,7 +546,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http public void asyncReadFillInterested() { - getEndPoint().tryFillInterested(_asyncReadCallback); + getEndPoint().fillInterested(_asyncReadCallback); } public void blockingReadFillInterested() diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AsyncIOServletTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AsyncIOServletTest.java index 0d9b00abb61..34e2d39e40b 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AsyncIOServletTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/AsyncIOServletTest.java @@ -980,7 +980,7 @@ public class AsyncIOServletTest extends AbstractTest while (input.isReady() && !input.isFinished()) { int read = input.read(); - System.err.printf("%x%n", read); + // System.err.printf("%x%n", read); readLatch.countDown(); } } From 10b7326c3c99c394a6586b741c5e551e87ba83d1 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 8 Feb 2017 15:53:30 +1100 Subject: [PATCH 3/3] Issue #1047 - ReadPendingException and then thread death. Tidy up write side. It cannot be the same as the read side as there is no registration for write interest. There is only write operations and the callbacks associated with them. --- .../jetty/server/HttpChannelState.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java index 35cf0e40fe7..c0c6db8e54f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java @@ -119,7 +119,7 @@ public class HttpChannelState private boolean _initial; private boolean _asyncReadPossible; private Interest _asyncRead=Interest.NONE; - private boolean _asyncWrite; // TODO refactor same as read + private boolean _asyncWritePossible; private long _timeoutMs=DEFAULT_TIMEOUT; private AsyncContextEvent _event; @@ -186,7 +186,7 @@ public class HttpChannelState _initial, _asyncRead, _asyncReadPossible, - _asyncWrite); + _asyncWritePossible); } } @@ -231,10 +231,10 @@ public class HttpChannelState return Action.READ_CALLBACK; } - if (_asyncWrite) + if (_asyncWritePossible) { _state=State.ASYNC_IO; - _asyncWrite=false; + _asyncWritePossible=false; return Action.WRITE_CALLBACK; } @@ -421,7 +421,7 @@ public class HttpChannelState case EXPIRED: _state=State.DISPATCHED; _async=Async.NOT_ASYNC; - action = Action.ERROR_DISPATCH; + action=Action.ERROR_DISPATCH; break; case STARTED: @@ -429,12 +429,12 @@ public class HttpChannelState { _state=State.ASYNC_IO; _asyncRead=Interest.NONE; - action = Action.READ_CALLBACK; + action=Action.READ_CALLBACK; } - else if (_asyncWrite) // TODO refactor same as read + else if (_asyncWritePossible) { - _asyncWrite=false; _state=State.ASYNC_IO; + _asyncWritePossible=false; action=Action.WRITE_CALLBACK; } else @@ -782,7 +782,7 @@ public class HttpChannelState _initial=true; _asyncReadPossible=false; _asyncRead=Interest.NONE; - _asyncWrite=false; + _asyncWritePossible=false; _timeoutMs=DEFAULT_TIMEOUT; _event=null; } @@ -807,7 +807,7 @@ public class HttpChannelState _initial=true; _asyncReadPossible=false; _asyncRead=Interest.NONE; - _asyncWrite=false; + _asyncWritePossible=false; _timeoutMs=DEFAULT_TIMEOUT; _event=null; } @@ -1062,7 +1062,7 @@ public class HttpChannelState try(Locker.Lock lock= _locker.lock()) { - _asyncWrite=true; + _asyncWritePossible=true; if (_state==State.ASYNC_WAIT) { _state=State.ASYNC_WOKEN;