Fixes #3929 - Deadlock between new HTTP2Connection() and Server.stop().
Updated code after review. Now a managed failed bean is restarted if its container is restarted. Added more test cases. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
f484b83c2e
commit
4b7ba20aae
|
@ -106,7 +106,7 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container,
|
||||||
switch (b._managed)
|
switch (b._managed)
|
||||||
{
|
{
|
||||||
case MANAGED:
|
case MANAGED:
|
||||||
if (l.isStopped())
|
if (l.isStopped() || l.isFailed())
|
||||||
start(l);
|
start(l);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.TypeUtil;
|
import org.eclipse.jetty.util.TypeUtil;
|
||||||
|
@ -675,4 +676,71 @@ public class ContainerLifeCycleTest
|
||||||
longLived.start();
|
longLived.start();
|
||||||
longLived.stop();
|
longLived.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailedManagedBeanCanBeRestarted() throws Exception
|
||||||
|
{
|
||||||
|
AtomicBoolean fail = new AtomicBoolean();
|
||||||
|
ContainerLifeCycle container = new ContainerLifeCycle();
|
||||||
|
ContainerLifeCycle bean1 = new ContainerLifeCycle();
|
||||||
|
ContainerLifeCycle bean2 = new ContainerLifeCycle()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void doStart() throws Exception
|
||||||
|
{
|
||||||
|
super.doStart();
|
||||||
|
// Fail only the first time.
|
||||||
|
if (fail.compareAndSet(false, true))
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ContainerLifeCycle bean3 = new ContainerLifeCycle();
|
||||||
|
container.addBean(bean1);
|
||||||
|
container.addBean(bean2);
|
||||||
|
container.addBean(bean3);
|
||||||
|
|
||||||
|
// Start the first time, it should fail.
|
||||||
|
assertThrows(RuntimeException.class, container::start);
|
||||||
|
assertTrue(container.isFailed());
|
||||||
|
assertTrue(bean1.isStopped());
|
||||||
|
assertTrue(bean2.isFailed());
|
||||||
|
assertTrue(bean3.isStopped());
|
||||||
|
|
||||||
|
// Re-start, it should succeed.
|
||||||
|
container.start();
|
||||||
|
assertTrue(container.isStarted());
|
||||||
|
assertTrue(bean1.isStarted());
|
||||||
|
assertTrue(bean2.isStarted());
|
||||||
|
assertTrue(bean3.isStarted());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailedAutoBeanIsNotRestarted() throws Exception
|
||||||
|
{
|
||||||
|
AtomicBoolean fail = new AtomicBoolean();
|
||||||
|
ContainerLifeCycle bean = new ContainerLifeCycle()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void doStart() throws Exception
|
||||||
|
{
|
||||||
|
super.doStart();
|
||||||
|
// Fail only the first time.
|
||||||
|
if (fail.compareAndSet(false, true))
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// The bean is started externally and fails.
|
||||||
|
assertThrows(RuntimeException.class, bean::start);
|
||||||
|
|
||||||
|
// The same bean now becomes part of a container.
|
||||||
|
ContainerLifeCycle container = new ContainerLifeCycle();
|
||||||
|
container.addBean(bean);
|
||||||
|
assertTrue(container.isAuto(bean));
|
||||||
|
|
||||||
|
// Start the container, the bean must not be managed.
|
||||||
|
container.start();
|
||||||
|
assertTrue(container.isStarted());
|
||||||
|
assertTrue(bean.isFailed());
|
||||||
|
assertTrue(container.isUnmanaged(bean));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue