This is an automated email from the ASF dual-hosted git repository.

clebertsuconic pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git


The following commit(s) were added to refs/heads/master by this push:
     new b1835fa  ARTEMIS-3037 JournalImpl#checkKnownRecordID() implementation 
can leave a thread hanging in WAITING state
     new 1db088e  This closes #3385
b1835fa is described below

commit b1835fa2d8bf2c54d1e2d5a3f2f1e0cb075adcb3
Author: Tomas Hofman <thof...@redhat.com>
AuthorDate: Thu Dec 17 11:52:25 2020 +0100

    ARTEMIS-3037 JournalImpl#checkKnownRecordID() implementation can leave a 
thread hanging in WAITING state
---
 .../artemis/core/journal/impl/JournalImpl.java     | 17 +++--
 .../extras/byteman/JournalImplConcurrencyTest.java | 73 ++++++++++++++++++++++
 2 files changed, 84 insertions(+), 6 deletions(-)

diff --git 
a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
 
b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
index e91b76b..8418174 100644
--- 
a/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
+++ 
b/artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/JournalImpl.java
@@ -1135,14 +1135,19 @@ public class JournalImpl extends JournalBase implements 
TestableJournal, Journal
       appendExecutor.execute(new Runnable() {
          @Override
          public void run() {
-            journalLock.readLock().lock();
             try {
+               journalLock.readLock().lock();
+               try {
 
-               known.set(records.containsKey(id)
-                  || pendingRecords.contains(id)
-                  || (compactor != null && compactor.containsRecord(id)));
-            } finally {
-               journalLock.readLock().unlock();
+                  known.set(records.containsKey(id)
+                          || pendingRecords.contains(id)
+                          || (compactor != null && 
compactor.containsRecord(id)));
+               } finally {
+                  journalLock.readLock().unlock();
+               }
+            } catch (Throwable t) {
+               known.fail(t);
+               throw t;
             }
          }
       });
diff --git 
a/tests/extra-tests/src/test/java/org/apache/activemq/artemis/tests/extras/byteman/JournalImplConcurrencyTest.java
 
b/tests/extra-tests/src/test/java/org/apache/activemq/artemis/tests/extras/byteman/JournalImplConcurrencyTest.java
new file mode 100644
index 0000000..5df1afa
--- /dev/null
+++ 
b/tests/extra-tests/src/test/java/org/apache/activemq/artemis/tests/extras/byteman/JournalImplConcurrencyTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.artemis.tests.extras.byteman;
+
+import org.apache.activemq.artemis.core.io.SequentialFileFactory;
+import 
org.apache.activemq.artemis.tests.unit.core.journal.impl.JournalImplTestBase;
+import 
org.apache.activemq.artemis.tests.unit.core.journal.impl.fakes.FakeSequentialFileFactory;
+import org.jboss.byteman.contrib.bmunit.BMRule;
+import org.jboss.byteman.contrib.bmunit.BMRules;
+import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.ExecutionException;
+
+@RunWith(BMUnitRunner.class)
+public class JournalImplConcurrencyTest extends JournalImplTestBase {
+
+   @Override
+   protected SequentialFileFactory getFileFactory() {
+      return new FakeSequentialFileFactory();
+   }
+
+
+   /**
+    * Tests that JournalImpl#checkKnownRecordID() doesn't hang when the 
executor thread fails with
+    * an exception before setting the future value.
+    */
+   @Test(timeout = 2000)
+   @BMRules(rules = {
+         @BMRule(
+               name = "BlockOnFinalLargeMessagePacket",
+               targetClass = 
"java.util.concurrent.locks.ReentrantReadWriteLock",
+               targetMethod = "readLock()",
+               targetLocation = "EXIT",
+               condition = 
"Thread.currentThread().getName().contains(\"ArtemisIOThread\")",
+               action = "throw RuntimeException(\"Injected exception\");"
+         )
+   })
+   public void testTryDelete() throws Exception {
+      setup(10, 10 * 1024, true);
+      createJournal();
+      startJournal();
+      load();
+      addTx(1, 1, 2, 3);
+
+      try {
+         tryDelete(1);
+         Assert.fail("Expected to throw exception injected by a byteman rule");
+      } catch (ExecutionException e) {
+         Assert.assertTrue(e.getCause() instanceof RuntimeException);
+         Assert.assertEquals("Injected exception", e.getCause().getMessage());
+      }
+
+      stopJournal();
+   }
+
+}

Reply via email to