diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java index aad9cecf35..637b21a15d 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java @@ -985,7 +985,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { } } - void stop(boolean failoverOnServerShutdown, final boolean criticalIOError, boolean restarting) { + public void stop(boolean failoverOnServerShutdown, final boolean criticalIOError, boolean restarting) { this.stop(failoverOnServerShutdown, criticalIOError, restarting, false); } @@ -1186,7 +1186,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { for (ActiveMQComponent externalComponent : externalComponents) { try { if (externalComponent instanceof ServiceComponent) { - ((ServiceComponent)externalComponent).stop(isShutdown); + ((ServiceComponent)externalComponent).stop(isShutdown || criticalIOError); } else { externalComponent.stop(); } diff --git a/artemis-web/pom.xml b/artemis-web/pom.xml index dbace47a44..21c9a1b254 100644 --- a/artemis-web/pom.xml +++ b/artemis-web/pom.xml @@ -75,6 +75,12 @@ tests test + + org.apache.activemq + artemis-junit + ${project.version} + test + io.netty netty-buffer diff --git a/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerCLITest.java b/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerCLITest.java new file mode 100644 index 0000000000..e624e6f14f --- /dev/null +++ b/artemis-web/src/test/java/org/apache/activemq/cli/test/WebServerCLITest.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.cli.test; + +import java.io.File; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.activemq.artemis.api.core.Pair; +import org.apache.activemq.artemis.api.core.client.ActiveMQClient; +import org.apache.activemq.artemis.cli.Artemis; +import org.apache.activemq.artemis.cli.commands.Run; +import org.apache.activemq.artemis.cli.commands.tools.LockAbstract; +import org.apache.activemq.artemis.core.server.ActiveMQComponent; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl; +import org.apache.activemq.artemis.core.server.management.ManagementContext; +import org.apache.activemq.artemis.jlibaio.LibaioContext; +import org.apache.activemq.artemis.junit.Wait; +import org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoader; +import org.apache.activemq.artemis.utils.ThreadLeakCheckRule; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +public class WebServerCLITest { + + @Rule + public TemporaryFolder temporaryFolder; + + @Rule + public ThreadLeakCheckRule leakCheckRule = new ThreadLeakCheckRule(); + + private String original = System.getProperty("java.security.auth.login.config"); + + public WebServerCLITest() { + File parent = new File("./target/tmp"); + parent.mkdirs(); + temporaryFolder = new TemporaryFolder(parent); + } + + @Before + public void setup() throws Exception { + System.setProperty("java.security.auth.login.config", temporaryFolder.getRoot().getAbsolutePath() + "/etc/login.config"); + Run.setEmbedded(true); + PropertiesLoader.resetUsersAndGroupsCache(); + } + + @After + public void tearDown() throws Exception { + ActiveMQClient.clearThreadPools(); + System.clearProperty("artemis.instance"); + System.clearProperty("artemis.instance.etc"); + Run.setEmbedded(false); + + if (original == null) { + System.clearProperty("java.security.auth.login.config"); + } else { + System.setProperty("java.security.auth.login.config", original); + } + + LockAbstract.unlock(); + } + + @Test + public void testStopEmbeddedWebServerOnCriticalIOError() throws Exception { + Run.setEmbedded(true); + File instance1 = new File(temporaryFolder.getRoot(), "instance_user"); + System.setProperty("java.security.auth.login.config", instance1.getAbsolutePath() + "/etc/login.config"); + Artemis.main("create", instance1.getAbsolutePath(), "--silent", "--no-autotune", "--no-amqp-acceptor", "--no-mqtt-acceptor", "--no-stomp-acceptor", "--no-hornetq-acceptor"); + System.setProperty("artemis.instance", instance1.getAbsolutePath()); + Object result = Artemis.internalExecute("run"); + ActiveMQServer activeMQServer = ((Pair) result).getB(); + List externalComponents = activeMQServer.getExternalComponents(); + + /** + * simulate critical IO error as this is what is eventually called by org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl.ShutdownOnCriticalErrorListener + */ + ((ActiveMQServerImpl) activeMQServer).stop(false, true, false); + + for (ActiveMQComponent externalComponent : externalComponents) { + assertTrue(Wait.waitFor(() -> externalComponent.isStarted() == false, 3000, 100)); + } + stopServer(); + } + + private void stopServer() throws Exception { + Artemis.internalExecute("stop"); + assertTrue(Run.latchRunning.await(5, TimeUnit.SECONDS)); + assertEquals(0, LibaioContext.getTotalMaxIO()); + } +}