From a0bd9d38876765161ae95883b9f19d41d67cc315 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Wed, 4 May 2016 11:43:50 +0200 Subject: [PATCH] Fixes #546 (Guard concurrent calls to ExecutionStrategy.execute()) Guarded invocations to execute() with a state change. --- .../util/thread/strategy/ProduceConsume.java | 25 +++++++++++++++++-- .../strategy/ProduceExecuteConsume.java | 23 ++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/ProduceConsume.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/ProduceConsume.java index 0971944df8b..debc55baf04 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/ProduceConsume.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/ProduceConsume.java @@ -34,6 +34,7 @@ public class ProduceConsume implements ExecutionStrategy, Runnable private final Producer _producer; private final Executor _executor; + private State _state = State.IDLE; public ProduceConsume(Producer producer, Executor executor) { @@ -44,16 +45,31 @@ public class ProduceConsume implements ExecutionStrategy, Runnable @Override public void execute() { + synchronized (this) + { + _state = _state == State.IDLE ? State.PRODUCE : State.EXECUTE; + if (_state == State.EXECUTE) + return; + } + // Iterate until we are complete. while (true) { // Produce a task. Runnable task = _producer.produce(); if (LOG.isDebugEnabled()) - LOG.debug("{} produced {}", this, task); + LOG.debug("{} produced {}", _producer, task); if (task == null) - break; + { + synchronized (this) + { + _state = _state == State.PRODUCE ? State.IDLE : State.PRODUCE; + if (_state == State.PRODUCE) + continue; + return; + } + } // Run the task. task.run(); @@ -80,4 +96,9 @@ public class ProduceConsume implements ExecutionStrategy, Runnable return new ProduceConsume(producer, executor); } } + + private enum State + { + IDLE, PRODUCE, EXECUTE + } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/ProduceExecuteConsume.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/ProduceExecuteConsume.java index ab7ddc171b7..f9400d50d9f 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/ProduceExecuteConsume.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/strategy/ProduceExecuteConsume.java @@ -35,6 +35,7 @@ public class ProduceExecuteConsume implements ExecutionStrategy private final Producer _producer; private final Executor _executor; + private State _state = State.IDLE; public ProduceExecuteConsume(Producer producer, Executor executor) { @@ -45,6 +46,13 @@ public class ProduceExecuteConsume implements ExecutionStrategy @Override public void execute() { + synchronized (this) + { + _state = _state == State.IDLE ? State.PRODUCE : State.EXECUTE; + if (_state == State.EXECUTE) + return; + } + // Iterate until we are complete. while (true) { @@ -54,7 +62,15 @@ public class ProduceExecuteConsume implements ExecutionStrategy LOG.debug("{} produced {}", _producer, task); if (task == null) - break; + { + synchronized (this) + { + _state = _state == State.PRODUCE ? State.IDLE : State.PRODUCE; + if (_state == State.PRODUCE) + continue; + return; + } + } // Execute the task. try @@ -94,4 +110,9 @@ public class ProduceExecuteConsume implements ExecutionStrategy return new ProduceExecuteConsume(producer, executor); } } + + private enum State + { + IDLE, PRODUCE, EXECUTE + } }