From 918cf625cc87961903db34e993e570abd6457dcf Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 15 Nov 2017 18:13:00 +0100 Subject: [PATCH 1/2] Issue #1958 Blocking timeout spurious wakeups (#1975) * Issue #1958 Blocking timeout Use tryFillInterested to allow retries on spurious wakeups Signed-off-by: Greg Wilkins --- .../java/org/eclipse/jetty/server/HttpConnection.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 6011d7eff0b..b7f51632dd7 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 @@ -564,7 +564,15 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http public void blockingReadFillInterested() { - getEndPoint().fillInterested(_blockingReadCallback); + // We try fillInterested here because of SSL and + // spurious wakeups. With blocking reads, we read in a loop + // that tries to read/parse content and blocks waiting if there is + // none available. The loop can be woken up by incoming encrypted + // bytes, which due to SSL might not produce any decrypted bytes. + // Thus the loop needs to register fill interest again. However if + // the loop is woken up spuriously, then the register interest again + // can result in a pending read exception, unless we use tryFillInterested. + getEndPoint().tryFillInterested(_blockingReadCallback); } public void blockingReadFailure(Throwable e) From 131f46df6445ec45357505949747eba4a4812bc1 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 16 Nov 2017 11:34:59 +0100 Subject: [PATCH 2/2] Improved dump of ManagedSelector. Now also dumping the actions. Signed-off-by: Simone Bordet --- .../org/eclipse/jetty/io/ManagedSelector.java | 30 ++++++++----------- .../util/component/ContainerLifeCycle.java | 10 +------ 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java index 0346f4c10e5..f2ffc393fea 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java @@ -28,6 +28,7 @@ import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -40,6 +41,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.jetty.util.component.ContainerLifeCycle; import org.eclipse.jetty.util.component.Dumpable; +import org.eclipse.jetty.util.component.DumpableCollection; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.ExecutionStrategy; @@ -226,29 +228,23 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable } } - @Override - public String dump() - { - super.dump(); - return ContainerLifeCycle.dump(this); - } - @Override public void dump(Appendable out, String indent) throws IOException { + super.dump(out, indent); Selector selector = _selector; - if (selector == null || !selector.isOpen()) - dumpBeans(out, indent); - else + if (selector != null && selector.isOpen()) { - final ArrayList dump = new ArrayList<>(selector.keys().size() * 2); - DumpKeys dumpKeys = new DumpKeys(dump); + List actions; + try (Locker.Lock lock = _locker.lock()) + { + actions = new ArrayList<>(_actions); + } + List keys = new ArrayList<>(selector.keys().size()); + DumpKeys dumpKeys = new DumpKeys(keys); submit(dumpKeys); dumpKeys.await(5, TimeUnit.SECONDS); - if (dump.isEmpty()) - dumpBeans(out, indent); - else - dumpBeans(out, indent, dump); + dump(out, indent, Arrays.asList(new DumpableCollection("keys", keys), new DumpableCollection("actions", actions))); } } @@ -512,7 +508,7 @@ public class ManagedSelector extends ContainerLifeCycle implements Dumpable } catch (Throwable x) { - _dumps.add(String.format("SelectionKey@%x[%s]", key.hashCode(), x)); + _dumps.add(String.format("SelectionKey@%x[%s]->%s", key.hashCode(), x, key.attachment())); } } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java index 5c9d177daf1..7ffc20bedab 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java @@ -660,13 +660,10 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container, int size = _beans.size(); for (Collection c : collections) size += c.size(); - if (size == 0) - return; int i = 0; for (Bean b : _beans) { - i++; - + ++i; switch(b._managed) { case POJO: @@ -697,20 +694,15 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container, else dumpObject(out, b._bean); break; - } } - if (i c : collections) { for (Object o : c) { i++; out.append(indent).append(" +> "); - if (o instanceof Dumpable) ((Dumpable)o).dump(out, indent + (i == size ? " " : " | ")); else